home *** CD-ROM | disk | FTP | other *** search
/ STraTOS 1997 April & May / STraTOS 1 - 1997 April & May.iso / CD01 / INTERNET / SITES / LITTLE / P3SRC.ZIP / ATARI / PARSE.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-07-03  |  127.6 KB  |  5,859 lines

  1. /****************************************************************************
  2. *                parse.c
  3. *
  4. *  This module implements a parser for the scene description files.
  5. *
  6. *  from Persistence of Vision(tm) Ray Tracer
  7. *  Copyright 1996 Persistence of Vision Team
  8. *---------------------------------------------------------------------------
  9. *  NOTICE: This source code file is provided so that users may experiment
  10. *  with enhancements to POV-Ray and to port the software to platforms other
  11. *  than those supported by the POV-Ray Team.  There are strict rules under
  12. *  which you are permitted to use this file.  The rules are in the file
  13. *  named POVLEGAL.DOC which should be distributed with this file. If
  14. *  POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  15. *  Team Coordinator by leaving a message in CompuServe's Graphics Developer's
  16. *  Forum.  The latest version of POV-Ray may be found there as well.
  17. *
  18. * This program is based on the popular DKB raytracer version 2.12.
  19. * DKBTrace was originally written by David K. Buck.
  20. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  21. *
  22. *****************************************************************************/
  23.  
  24. #include "frame.h"
  25. #include "vector.h"
  26. #include "povproto.h"
  27. #include "parse.h"
  28. #include "parstxtr.h"
  29. #include "atmosph.h"
  30. #include "bezier.h"   
  31. #include "blob.h"     
  32. #include "boxes.h"
  33. #include "colour.h"
  34. #include "cones.h"    
  35. #include "csg.h"      
  36. #include "discs.h"
  37. #include "express.h"  
  38. #include "fractal.h"
  39. #include "gif.h"      
  40. #include "halos.h"
  41. #include "hfield.h"
  42. #include "iff.h"      
  43. #include "image.h"    
  44. #include "lathe.h"    
  45. #include "polysolv.h"
  46. #include "matrices.h"
  47. #include "mesh.h"
  48. #include "normal.h"
  49. #include "objects.h"
  50. #include "octree.h"
  51. #include "pigment.h"
  52. #include "planes.h"
  53. #include "poly.h"
  54. #include "polygon.h"
  55. #include "povray.h"   
  56. #include "pgm.h"      
  57. #include "ppm.h"      
  58. #include "prism.h"    
  59. #include "quadrics.h" 
  60. #include "radiosit.h"      
  61. #include "render.h"   
  62. #include "sor.h"      
  63. #include "spheres.h"  
  64. #include "super.h"
  65. #include "targa.h"    
  66. #include "texture.h"  
  67. #include "tokenize.h" 
  68. #include "torus.h"
  69. #include "triangle.h" 
  70. #include "truetype.h" 
  71.  
  72.  
  73. /*****************************************************************************
  74. * Local preprocessor defines
  75. ******************************************************************************/
  76.  
  77. /* Volume that is considered to be infinite. [DB 9/94] */
  78.  
  79. #define INFINITE_VOLUME BOUND_HUGE
  80.  
  81.  
  82. /*****************************************************************************
  83. * Local typedefs
  84. ******************************************************************************/
  85.  
  86.  
  87.  
  88. /*****************************************************************************
  89. * Local variables
  90. ******************************************************************************/
  91.  
  92. short Have_Vector;
  93. short Not_In_Default;
  94. short Ok_To_Declare;
  95.  
  96. static TOKEN *Brace_Stack;
  97. static int Brace_Index;
  98. static CAMERA *Default_Camera;
  99.  
  100.  
  101.  
  102. /*****************************************************************************
  103. * Static functions
  104. ******************************************************************************/
  105.  
  106. static TRANSFORM *Parse_Transform PARAMS((void));
  107. static void Frame_Init PARAMS((void));
  108. static void Parse_Coeffs PARAMS((int order, DBL *Coeffs));
  109.  
  110. static OBJECT *Parse_Bicubic_Patch PARAMS((void));
  111. static OBJECT *Parse_Blob PARAMS((void));
  112. static OBJECT *Parse_Bound_Clip PARAMS((void));
  113. static OBJECT *Parse_Box PARAMS((void));
  114. static OBJECT *Parse_Cone PARAMS((void));
  115. static OBJECT *Parse_CSG PARAMS((int CSG_Type));
  116. static OBJECT *Parse_Cylinder PARAMS((void));
  117. static OBJECT *Parse_Disc PARAMS((void));
  118. static OBJECT *Parse_Julia_Fractal PARAMS((void));
  119. static OBJECT *Parse_HField PARAMS((void));
  120. static OBJECT *Parse_Lathe PARAMS((void));
  121. static OBJECT *Parse_Light_Source PARAMS((void));
  122. static OBJECT *Parse_Object_Id PARAMS((void));
  123. static OBJECT *Parse_Plane PARAMS((void));
  124. static OBJECT *Parse_Poly PARAMS((int order));
  125. static OBJECT *Parse_Polygon PARAMS((void));
  126. static OBJECT *Parse_Prism PARAMS((void));
  127. static OBJECT *Parse_Quadric PARAMS((void));
  128. static OBJECT *Parse_Smooth_Triangle PARAMS((void));
  129. static OBJECT *Parse_Sor PARAMS((void));
  130. static OBJECT *Parse_Sphere PARAMS((void));
  131. static OBJECT *Parse_Superellipsoid PARAMS((void));
  132. static OBJECT *Parse_Torus PARAMS((void));
  133. static OBJECT *Parse_Triangle PARAMS((void));
  134. static OBJECT *Parse_Mesh PARAMS((void));
  135. static TEXTURE *Parse_Mesh_Texture PARAMS((void));
  136. static OBJECT *Parse_TrueType PARAMS((void));
  137. static void Parse_Blob_Element_Mods PARAMS((BLOB_ELEMENT *Element));
  138.  
  139. static void Parse_Camera PARAMS((CAMERA **Camera_Ptr));
  140. static void Parse_Frame PARAMS((void));
  141.  
  142. static char *Get_Token_String PARAMS((TOKEN Token_Id));
  143. static int Test_Redefine PARAMS((int Previous, int a));
  144. static void Destroy_Constants PARAMS((void));
  145. static void Found_Instead PARAMS((void));
  146. static void Link PARAMS((OBJECT *New_Object,OBJECT **Field,OBJECT **Old_Object_List));
  147. static void Link_To_Frame PARAMS((OBJECT *Object));
  148. static void Post_Process PARAMS((OBJECT *Object, OBJECT *Parent));
  149. static void Parse_Global_Settings PARAMS((void));
  150. static void Global_Setting_Warn PARAMS((void));
  151.  
  152. static void Set_CSG_Children_Hollow PARAMS((OBJECT *Object, int hollow));
  153.  
  154.  
  155.  
  156. /*****************************************************************************
  157. *
  158. * FUNCTION
  159. *
  160. * INPUT
  161. *
  162. * OUTPUT
  163. *
  164. * RETURNS
  165. *
  166. * AUTHOR
  167. *   
  168. * DESCRIPTION
  169. *
  170. * CHANGES
  171. *
  172. ******************************************************************************/
  173.  
  174. /* Parse the file. */
  175. void Parse ()
  176. {
  177.   Initialize_Tokenizer();
  178.   Brace_Stack = (TOKEN *)POV_MALLOC(MAX_BRACES*sizeof (TOKEN), "brace stack");
  179.   Brace_Index = 0;
  180.  
  181.   Default_Camera = Create_Camera();
  182.  
  183.   Default_Texture = Create_Texture();
  184.  
  185.   Default_Texture->Pigment = Create_Pigment();
  186.   Default_Texture->Tnormal = NULL;
  187.   Default_Texture->Finish  = Create_Finish();
  188.   Default_Texture->Halo    = NULL;
  189.  
  190.   Not_In_Default = TRUE;
  191.   Ok_To_Declare = TRUE;
  192.  
  193.   Frame_Init ();
  194.   
  195.   Stage = STAGE_PARSING;
  196.  
  197.   Parse_Frame ();
  198.  
  199.   if (Frame.Objects == NULL)
  200.   {
  201.     Error ("No objects in scene.");
  202.   }
  203.      
  204.   Stage = STAGE_CLEANUP_PARSE;
  205.  
  206.   Terminate_Tokenizer();
  207.   Destroy_Constants ();
  208.   Destroy_Textures(Default_Texture); 
  209.   Destroy_Camera(Default_Camera); 
  210.   POV_FREE (Brace_Stack);
  211.  
  212.   Default_Texture = NULL;
  213.   Default_Camera = NULL;
  214.   Brace_Stack = NULL;
  215. }
  216.  
  217.  
  218.  
  219. /*****************************************************************************
  220. *
  221. * FUNCTION
  222. *
  223. * INPUT
  224. *   
  225. * OUTPUT
  226. *   
  227. * RETURNS
  228. *   
  229. * AUTHOR
  230. *   
  231. * DESCRIPTION
  232. *
  233. * CHANGES
  234. *
  235. ******************************************************************************/
  236.  
  237. /* Set up the fields in the frame to default values. */
  238. static
  239. void Frame_Init ()
  240.   {
  241.    Frame.Camera = Copy_Camera(Default_Camera);
  242.    Frame.Number_Of_Light_Sources = 0;  
  243.    Frame.Light_Sources = NULL;
  244.    Frame.Objects = NULL;
  245.    Frame.Atmosphere_IOR = 1.0;
  246.    Frame.Antialias_Threshold = opts.Antialias_Threshold;
  247.  
  248. /* dmf -- the first is physically "more correct".  The second works better */
  249. /*   Make_Colour (Frame.Irid_Wavelengths, 0.70, 0.52, 0.48); */
  250.    Make_Colour (Frame.Irid_Wavelengths, 0.25, 0.18, 0.14);
  251.    Make_Colour (Frame.Background_Colour, 0.0, 0.0, 0.0);
  252.    Make_Colour (Frame.Ambient_Light, 1.0, 1.0, 1.0);
  253.  
  254.    /* Init atmospheric stuff. [DB 12/94] */
  255.  
  256.    Frame.Atmosphere = NULL;
  257.  
  258.    Frame.Fog = NULL;
  259.  
  260.    Frame.Rainbow = NULL;
  261.  
  262.    Frame.Skysphere = NULL;
  263.   }
  264.  
  265.  
  266.  
  267. /*****************************************************************************
  268. *
  269. * FUNCTION
  270. *
  271. * INPUT
  272. *   
  273. * OUTPUT
  274. *   
  275. * RETURNS
  276. *   
  277. * AUTHOR
  278. *   
  279. * DESCRIPTION
  280. *
  281. * CHANGES
  282. *
  283. ******************************************************************************/
  284.  
  285. void Parse_Begin ()
  286.   {
  287.    char *front;
  288.  
  289.    Brace_Stack[++Brace_Index]=Token.Token_Id;
  290.  
  291.    Get_Token ();
  292.  
  293.    if (Token.Token_Id == LEFT_CURLY_TOKEN)
  294.      return;
  295.  
  296.    front = Get_Token_String (Brace_Stack[Brace_Index]);
  297.  
  298.    Where_Error ();
  299.    Error_Line ("Missing { after %s, ", front);
  300.    Found_Instead ();
  301.   }
  302.  
  303.  
  304.  
  305. /*****************************************************************************
  306. *
  307. * FUNCTION
  308. *
  309. * INPUT
  310. *   
  311. * OUTPUT
  312. *   
  313. * RETURNS
  314. *   
  315. * AUTHOR
  316. *   
  317. * DESCRIPTION
  318. *
  319. * CHANGES
  320. *
  321. ******************************************************************************/
  322.  
  323. void Parse_End ()
  324.   {
  325.    char *front;
  326.  
  327.    Get_Token ();
  328.  
  329.    if (Token.Token_Id == RIGHT_CURLY_TOKEN)
  330.      {
  331.       Brace_Index--;
  332.       return;
  333.      }
  334.  
  335.    front = Get_Token_String (Brace_Stack[Brace_Index]);
  336.  
  337.    Where_Error ();
  338.    Error_Line("No matching } in %s,", front);
  339.    Found_Instead ();
  340.   }
  341.  
  342.  
  343.  
  344. /*****************************************************************************
  345. *
  346. * FUNCTION
  347. *
  348. * INPUT
  349. *   
  350. * OUTPUT
  351. *   
  352. * RETURNS
  353. *   
  354. * AUTHOR
  355. *   
  356. * DESCRIPTION
  357. *
  358. * CHANGES
  359. *
  360. ******************************************************************************/
  361.  
  362. static OBJECT *Parse_Object_Id ()
  363.   {
  364.    OBJECT *Object;
  365.  
  366.    EXPECT
  367.      CASE (OBJECT_ID_TOKEN)
  368.        Warn_State(OBJECT_ID_TOKEN, OBJECT_TOKEN);
  369.        Object = Copy_Object((OBJECT *) Token.Constant_Data);
  370.        Parse_Object_Mods (Object);
  371.        EXIT
  372.      END_CASE
  373.  
  374.      OTHERWISE
  375.        Object = NULL;
  376.        UNGET
  377.        EXIT
  378.      END_CASE
  379.    END_EXPECT
  380.  
  381.    return (Object);
  382.   }
  383.  
  384.  
  385.  
  386. /*****************************************************************************
  387. *
  388. * FUNCTION
  389. *
  390. * INPUT
  391. *   
  392. * OUTPUT
  393. *   
  394. * RETURNS
  395. *   
  396. * AUTHOR
  397. *   
  398. * DESCRIPTION
  399. *
  400. * CHANGES
  401. *
  402. ******************************************************************************/
  403.  
  404. void Parse_Comma ()
  405.   {
  406.    Get_Token();
  407.    if (Token.Token_Id != COMMA_TOKEN)
  408.      {
  409.       UNGET;
  410.      }
  411.   }
  412.  
  413.  
  414.  
  415. /*****************************************************************************
  416. *
  417. * FUNCTION
  418. *
  419. * INPUT
  420. *   
  421. * OUTPUT
  422. *   
  423. * RETURNS
  424. *   
  425. * AUTHOR
  426. *   
  427. * DESCRIPTION
  428. *
  429. * CHANGES
  430. *
  431. ******************************************************************************/
  432.  
  433. static void Parse_Coeffs(order, Coeffs)
  434.   int order;
  435.   DBL *Coeffs;
  436.   {
  437.    int i;
  438.  
  439.    EXPECT
  440.      CASE (LEFT_ANGLE_TOKEN)
  441.        Coeffs[0] = Parse_Float();
  442.        for (i = 1; i < term_counts(order); i++)
  443.          {
  444.           Parse_Comma();
  445.           Coeffs[i] = Parse_Float();
  446.          }
  447.        GET (RIGHT_ANGLE_TOKEN);
  448.        EXIT
  449.      END_CASE
  450.  
  451.      OTHERWISE
  452.        Parse_Error (LEFT_ANGLE_TOKEN);
  453.      END_CASE
  454.    END_EXPECT
  455.   }
  456.  
  457.  
  458.  
  459. /*****************************************************************************
  460. *
  461. * FUNCTION
  462. *
  463. * INPUT
  464. *
  465. * OUTPUT
  466. *
  467. * RETURNS
  468. *
  469. * AUTHOR
  470. *
  471. * DESCRIPTION
  472. *
  473. * CHANGES
  474. *
  475. ******************************************************************************/
  476.  
  477. static
  478. OBJECT *Parse_Bound_Clip ()
  479.   {
  480.    VECTOR Local_Vector;
  481.    MATRIX Local_Matrix;
  482.    TRANSFORM Local_Trans;
  483.    OBJECT *First, *Current, *Prev;
  484.  
  485.    First = Prev = NULL;
  486.  
  487.    while ((Current = Parse_Object ()) != NULL)
  488.      {
  489.       if (Current->Type & (TEXTURED_OBJECT+PATCH_OBJECT))
  490.         Error ("Illegal texture or patch in clip or bound.");
  491.       if (First == NULL)
  492.         First = Current;
  493.       if (Prev != NULL)
  494.         Prev->Sibling = Current;
  495.       Prev = Current;
  496.      }
  497.  
  498.    EXPECT
  499.      CASE (TRANSLATE_TOKEN)
  500.        Parse_Vector (Local_Vector);
  501.        Compute_Translation_Transform(&Local_Trans, Local_Vector);
  502.        for (Current = First; Current != NULL; Current = Current->Sibling)
  503.        {
  504.          Translate_Object (Current, Local_Vector, &Local_Trans);
  505.        }
  506.      END_CASE
  507.  
  508.      CASE (ROTATE_TOKEN)
  509.        Parse_Vector (Local_Vector);
  510.        Compute_Rotation_Transform(&Local_Trans, Local_Vector);
  511.        for (Current = First; Current != NULL; Current = Current->Sibling)
  512.        {
  513.          Rotate_Object (Current, Local_Vector, &Local_Trans);
  514.        }
  515.      END_CASE
  516.  
  517.      CASE (SCALE_TOKEN)
  518.        Parse_Scale_Vector (Local_Vector);
  519.        Compute_Scaling_Transform(&Local_Trans, Local_Vector);
  520.        for (Current = First; Current != NULL; Current = Current->Sibling)
  521.        {
  522.          Scale_Object (Current, Local_Vector, &Local_Trans);
  523.        }
  524.      END_CASE
  525.  
  526.      CASE (TRANSFORM_TOKEN)
  527.        GET(TRANSFORM_ID_TOKEN)
  528.        for (Current = First; Current != NULL; Current = Current->Sibling)
  529.        {
  530.          Transform_Object (Current, (TRANSFORM *)Token.Constant_Data);
  531.        }
  532.      END_CASE
  533.  
  534.      CASE (MATRIX_TOKEN)
  535.        Parse_Matrix (Local_Matrix);
  536.        Compute_Matrix_Transform(&Local_Trans, Local_Matrix);
  537.        for (Current = First; Current != NULL; Current = Current->Sibling)
  538.        {
  539.          Transform_Object (Current, &Local_Trans);
  540.        }
  541.      END_CASE
  542.  
  543.      OTHERWISE
  544.        UNGET
  545.        EXIT
  546.      END_CASE
  547.    END_EXPECT
  548.  
  549.    if (First==NULL)
  550.    {
  551.       Parse_Error_Str("object");
  552.    }
  553.  
  554.    return (First);
  555.   }
  556.  
  557.  
  558.  
  559. /*****************************************************************************
  560. *
  561. * FUNCTION
  562. *
  563. * INPUT
  564. *   
  565. * OUTPUT
  566. *   
  567. * RETURNS
  568. *   
  569. * AUTHOR
  570. *   
  571. * DESCRIPTION
  572. *
  573. * CHANGES
  574. *
  575. ******************************************************************************/
  576.  
  577. void Parse_Object_Mods (Object)
  578.   OBJECT *Object;
  579.   {
  580.    DBL Temp_Water_Level;
  581.    DBL V1, V2;
  582.    VECTOR Min, Max;  
  583.    VECTOR Local_Vector;
  584.    MATRIX Local_Matrix;
  585.    TRANSFORM Local_Trans;
  586.    BBOX BBox;
  587.    OBJECT *Sib;
  588.    TEXTURE *Local_Texture;
  589.    OBJECT *Temp1_Object;
  590.    OBJECT *Temp2_Object;
  591.    COLOUR Local_Colour;
  592.  
  593.    EXPECT
  594.      CASE_COLOUR
  595.        Parse_Colour (Local_Colour);
  596.        if (opts.Language_Version < 1.5)
  597.          if (Object->Texture != NULL)
  598.            if (Object->Texture->Type == PLAIN_PATTERN)
  599.              if (opts.Quality_Flags & Q_QUICKC)
  600.              {
  601.               Assign_Colour(Object->Texture->Pigment->Colour,Local_Colour);
  602.               break;  /* acts like END_CASE */
  603.              }
  604.        Warn(0.0, "Quick color belongs in texture. Color ignored.");
  605.      END_CASE
  606.  
  607.      CASE (TRANSLATE_TOKEN)
  608.        Parse_Vector (Local_Vector);
  609.        Compute_Translation_Transform(&Local_Trans, Local_Vector);
  610.        Translate_Object (Object, Local_Vector, &Local_Trans);
  611.      END_CASE
  612.  
  613.      CASE (ROTATE_TOKEN)
  614.        Parse_Vector (Local_Vector);
  615.        Compute_Rotation_Transform(&Local_Trans, Local_Vector);
  616.        Rotate_Object (Object, Local_Vector, &Local_Trans);
  617.      END_CASE
  618.  
  619.      CASE (SCALE_TOKEN)
  620.        Parse_Scale_Vector (Local_Vector);
  621.        Compute_Scaling_Transform(&Local_Trans, Local_Vector);
  622.        Scale_Object (Object, Local_Vector, &Local_Trans);
  623.      END_CASE
  624.  
  625.      CASE (TRANSFORM_TOKEN)
  626.        GET(TRANSFORM_ID_TOKEN)
  627.        Transform_Object (Object, (TRANSFORM *)Token.Constant_Data);
  628.      END_CASE
  629.  
  630.      CASE (MATRIX_TOKEN)
  631.        Parse_Matrix (Local_Matrix);
  632.        Compute_Matrix_Transform(&Local_Trans, Local_Matrix);
  633.        Transform_Object (Object, &Local_Trans);
  634.      END_CASE
  635.  
  636.      CASE (BOUNDED_BY_TOKEN)
  637.        Parse_Begin ();
  638.        if (Object->Bound != NULL)
  639.          if (Object->Clip == Object->Bound)
  640.            Error ("Cannot add bounds after linking bounds and clips.");
  641.  
  642.        EXPECT
  643.          CASE (CLIPPED_BY_TOKEN)
  644.            if (Object->Bound != NULL)
  645.              Error ("Cannot link clips with previous bounds.");
  646.            Object->Bound = Object->Clip;
  647.            EXIT
  648.          END_CASE
  649.  
  650.          OTHERWISE
  651.            UNGET
  652.            Temp1_Object = Temp2_Object = Parse_Bound_Clip ();
  653.            while (Temp2_Object->Sibling != NULL)
  654.              Temp2_Object = Temp2_Object->Sibling;
  655.            Temp2_Object->Sibling = Object->Bound;
  656.            Object->Bound = Temp1_Object;
  657.            EXIT
  658.          END_CASE
  659.        END_EXPECT
  660.  
  661.        Parse_End ();
  662.      END_CASE
  663.  
  664.      CASE (CLIPPED_BY_TOKEN)
  665.        Parse_Begin ();
  666.        if (Object->Clip != NULL)
  667.          if (Object->Clip == Object->Bound)
  668.            Error ("Cannot add clips after linking bounds and clips.");
  669.  
  670.        EXPECT
  671.          CASE (BOUNDED_BY_TOKEN)
  672.            if (Object->Clip != NULL)
  673.              Error ("Cannot link bounds with previous clips.");
  674.            Object->Clip = Object->Bound;
  675.            EXIT
  676.          END_CASE
  677.  
  678.          OTHERWISE
  679.            UNGET
  680.            Temp1_Object = Temp2_Object = Parse_Bound_Clip ();
  681.            while (Temp2_Object->Sibling != NULL)
  682.              Temp2_Object = Temp2_Object->Sibling;
  683.            Temp2_Object->Sibling = Object->Clip;
  684.            Object->Clip = Temp1_Object;
  685.  
  686.            /* Compute quadric bounding box before transformations. [DB 8/94] */
  687.  
  688.            if (Object->Methods == &Quadric_Methods)
  689.            {
  690.              Make_Vector(Min, -BOUND_HUGE, -BOUND_HUGE, -BOUND_HUGE);
  691.              Make_Vector(Max,  BOUND_HUGE,  BOUND_HUGE,  BOUND_HUGE);
  692.  
  693.              Compute_Quadric_BBox((QUADRIC *)Object, Min, Max);
  694.            }
  695.            EXIT
  696.          END_CASE
  697.        END_EXPECT
  698.  
  699.        Parse_End ();
  700.      END_CASE
  701.  
  702.      CASE (TEXTURE_TOKEN)
  703.        Object->Type |= TEXTURED_OBJECT;
  704.        Parse_Begin ();
  705.        Local_Texture = Parse_Texture ();
  706.        Parse_End ();
  707.        Link_Textures(&(Object->Texture), Local_Texture);
  708.      END_CASE
  709.  
  710.      CASE4 (PIGMENT_TOKEN, TNORMAL_TOKEN, FINISH_TOKEN, HALO_TOKEN)
  711.        Object->Type |= TEXTURED_OBJECT;
  712.        if (Object->Texture == NULL)
  713.          Object->Texture = Copy_Textures(Default_Texture);
  714.        else
  715.          if (Object->Texture->Type != PLAIN_PATTERN)
  716.            Link_Textures(&(Object->Texture), Copy_Textures(Default_Texture));
  717.        UNGET
  718.        EXPECT
  719.          CASE (PIGMENT_TOKEN)
  720.            Parse_Begin ();
  721.            Parse_Pigment ( &(Object->Texture->Pigment) );
  722.            Parse_End ();
  723.          END_CASE
  724.  
  725.          CASE (TNORMAL_TOKEN)
  726.            Parse_Begin ();
  727.            Parse_Tnormal ( &(Object->Texture->Tnormal) );
  728.            Parse_End ();
  729.          END_CASE
  730.  
  731.          CASE (FINISH_TOKEN)
  732.            Parse_Finish ( &(Object->Texture->Finish) );
  733.          END_CASE
  734.  
  735.          CASE (HALO_TOKEN)
  736.            Parse_Halo ( &(Object->Texture->Halo) );
  737.          END_CASE
  738.  
  739.          OTHERWISE
  740.            UNGET
  741.            EXIT
  742.          END_CASE
  743.        END_EXPECT
  744.      END_CASE
  745.  
  746.      CASE (INVERSE_TOKEN)
  747.        if (Object->Type & PATCH_OBJECT)
  748.          Warn (0.0, "Cannot invert a patch object.");
  749.        Invert_Object (Object);
  750.      END_CASE
  751.  
  752.      CASE (STURM_TOKEN)
  753.        if (!(Object->Type & STURM_OK_OBJECT))
  754.          Not_With ("sturm","this object");
  755.        Bool_Flag (Object, STURM_FLAG, (Allow_Float(1.0) > 0.0));
  756.      END_CASE
  757.  
  758.      CASE (WATER_LEVEL_TOKEN)
  759.        if (!(Object->Type & WATER_LEVEL_OK_OBJECT))
  760.          Not_With ("water_level","this object");
  761.        Temp_Water_Level = Parse_Float();
  762.        if (opts.Language_Version < 2.0)
  763.          Temp_Water_Level /=256.0;
  764.        ((HFIELD *) Object)->bounding_box->bounds[0][Y] = 65536.0 * Temp_Water_Level;
  765.      END_CASE
  766.  
  767.      CASE (SMOOTH_TOKEN)
  768.        if (!(Object->Type & SMOOTH_OK_OBJECT))
  769.          Not_With ("smooth","this object");
  770.        Set_Flag(Object, SMOOTHED_FLAG);
  771.        Object->Type |= DOUBLE_ILLUMINATE;
  772.      END_CASE
  773.  
  774.      CASE (NO_SHADOW_TOKEN)
  775.        Set_Flag(Object, NO_SHADOW_FLAG);
  776.      END_CASE
  777.  
  778.      CASE (LIGHT_SOURCE_TOKEN)
  779.        Error("Light source must be defined using new syntax.");
  780.      END_CASE
  781.  
  782.      CASE(HIERARCHY_TOKEN)
  783.        if (!(Object->Type & HIERARCHY_OK_OBJECT))
  784.          Not_With ("hierarchy", "this object");
  785.        Bool_Flag (Object, HIERARCHY_FLAG, (Allow_Float(1.0) > 0.0));
  786.      END_CASE
  787.  
  788.      CASE(HOLLOW_TOKEN)
  789.        Bool_Flag (Object, HOLLOW_FLAG, (Allow_Float(1.0) > 0.0));
  790.        Set_Flag (Object, HOLLOW_SET_FLAG);
  791.        if ((Object->Methods == &CSG_Intersection_Methods) ||
  792.            (Object->Methods == &CSG_Merge_Methods) ||
  793.            (Object->Methods == &CSG_Union_Methods))
  794.        {
  795.          Set_CSG_Children_Hollow(Object, Test_Flag(Object, HOLLOW_FLAG));
  796.        }
  797.      END_CASE
  798.  
  799.      OTHERWISE
  800.        UNGET
  801.        EXIT
  802.      END_CASE
  803.    END_EXPECT
  804.  
  805.    /*
  806.     * Assign bounding objects' bounding box to object
  807.     * if object's bounding box is larger. [DB 9/94]
  808.     */
  809.  
  810.    if (Object->Bound != NULL)
  811.    {
  812.      /* Get bounding objects bounding box. */
  813.  
  814.      Make_Vector(Min, -BOUND_HUGE, -BOUND_HUGE, -BOUND_HUGE);
  815.      Make_Vector(Max,  BOUND_HUGE,  BOUND_HUGE,  BOUND_HUGE);
  816.  
  817.      for (Sib = Object->Bound; Sib != NULL; Sib = Sib->Sibling)
  818.      {
  819.        if (!Test_Flag(Sib, INVERTED_FLAG))
  820.        {
  821.          Min[X] = max(Min[X], Sib->BBox.Lower_Left[X]);
  822.          Min[Y] = max(Min[Y], Sib->BBox.Lower_Left[Y]);
  823.          Min[Z] = max(Min[Z], Sib->BBox.Lower_Left[Z]);
  824.          Max[X] = min(Max[X], Sib->BBox.Lower_Left[X] + Sib->BBox.Lengths[X]);
  825.          Max[Y] = min(Max[Y], Sib->BBox.Lower_Left[Y] + Sib->BBox.Lengths[Y]);
  826.          Max[Z] = min(Max[Z], Sib->BBox.Lower_Left[Z] + Sib->BBox.Lengths[Z]);
  827.        }
  828.      }
  829.  
  830.      Make_BBox_from_min_max(BBox, Min, Max);
  831.  
  832.      /* Get bounding boxes' volumes. */
  833.  
  834.      BOUNDS_VOLUME(V1, BBox);
  835.      BOUNDS_VOLUME(V2, Object->BBox);
  836.  
  837.      if (V1 < V2)
  838.      {
  839.        Object->BBox = BBox;
  840.      }
  841.    }
  842.  
  843.    /*
  844.     * Assign clipping objects' bounding box to object
  845.     * if object's bounding box is larger. [DB 9/94]
  846.     */
  847.  
  848.    if (Object->Clip != NULL)
  849.    {
  850.      /* Get clipping objects bounding box. */
  851.  
  852.      Make_Vector(Min, -BOUND_HUGE, -BOUND_HUGE, -BOUND_HUGE);
  853.      Make_Vector(Max,  BOUND_HUGE,  BOUND_HUGE,  BOUND_HUGE);
  854.  
  855.      for (Sib = Object->Clip; Sib != NULL; Sib = Sib->Sibling)
  856.      {
  857.        if (!Test_Flag(Sib, INVERTED_FLAG))
  858.        {
  859.          Min[X] = max(Min[X], Sib->BBox.Lower_Left[X]);
  860.          Min[Y] = max(Min[Y], Sib->BBox.Lower_Left[Y]);
  861.          Min[Z] = max(Min[Z], Sib->BBox.Lower_Left[Z]);
  862.          Max[X] = min(Max[X], Sib->BBox.Lower_Left[X] + Sib->BBox.Lengths[X]);
  863.          Max[Y] = min(Max[Y], Sib->BBox.Lower_Left[Y] + Sib->BBox.Lengths[Y]);
  864.          Max[Z] = min(Max[Z], Sib->BBox.Lower_Left[Z] + Sib->BBox.Lengths[Z]);
  865.        }
  866.      }
  867.  
  868.      Make_BBox_from_min_max(BBox, Min, Max);
  869.  
  870.      /* Get bounding boxes' volumes. */
  871.  
  872.      BOUNDS_VOLUME(V1, BBox);
  873.      BOUNDS_VOLUME(V2, Object->BBox);
  874.  
  875.      if (V1 < V2)
  876.      {
  877.        Object->BBox = BBox;
  878.      }
  879.    }
  880.  
  881.    Parse_End ();
  882.   }
  883.  
  884.  
  885.  
  886. /*****************************************************************************
  887. *
  888. * FUNCTION
  889. *
  890. *  Set_CSG_Children_Hollow
  891. *
  892. * INPUT
  893. *
  894. * OUTPUT
  895. *
  896. * RETURNS
  897. *
  898. * AUTHOR
  899. *
  900. * DESCRIPTION
  901. *
  902. * CHANGES
  903. *
  904. ******************************************************************************/
  905.  
  906. static void Set_CSG_Children_Hollow(Object, hollow)
  907. OBJECT *Object;
  908. int hollow;
  909. {
  910.   OBJECT *Sib;
  911.  
  912.   for (Sib = ((CSG *)Object)->Children; Sib != NULL; Sib = Sib->Sibling)
  913.   {
  914.     if (!Test_Flag(Sib, HOLLOW_SET_FLAG))
  915.     {
  916.       if ((Sib->Methods == &CSG_Intersection_Methods) ||
  917.           (Sib->Methods == &CSG_Merge_Methods) ||
  918.           (Sib->Methods == &CSG_Union_Methods))
  919.       {
  920.         Set_CSG_Children_Hollow(Sib, hollow);
  921.       }
  922.       else
  923.       {
  924.         Sib->Flags = (Sib->Flags & (~HOLLOW_FLAG)) | hollow;
  925.       }
  926.     }
  927.   }
  928. }
  929.  
  930.  
  931.  
  932. /*****************************************************************************
  933. *
  934. * FUNCTION
  935. *
  936. * INPUT
  937. *
  938. * OUTPUT
  939. *
  940. * RETURNS
  941. *
  942. * AUTHOR
  943. *
  944. * DESCRIPTION
  945. *
  946. * CHANGES
  947. *
  948. ******************************************************************************/
  949.  
  950. static OBJECT *Parse_Sphere()
  951. {
  952.   SPHERE *Object;
  953.  
  954.   Parse_Begin();
  955.  
  956.   if ((Object = (SPHERE *)Parse_Object_Id()) != NULL)
  957.   {
  958.     return ((OBJECT *) Object);
  959.   }
  960.  
  961.   Object = Create_Sphere();
  962.  
  963.   Parse_Vector(Object->Center);
  964.  
  965.   Parse_Comma();
  966.  
  967.   Object->Radius = Parse_Float();
  968.  
  969.   Compute_Sphere_BBox(Object);  
  970.  
  971.   Parse_Object_Mods((OBJECT *)Object);
  972.  
  973.   return((OBJECT *)Object);
  974. }
  975.  
  976.  
  977.  
  978. /*****************************************************************************
  979. *
  980. * FUNCTION
  981. *
  982. * INPUT
  983. *   
  984. * OUTPUT
  985. *   
  986. * RETURNS
  987. *   
  988. * AUTHOR
  989. *   
  990. * DESCRIPTION
  991. *
  992. * CHANGES
  993. *
  994. ******************************************************************************/
  995.  
  996. static
  997. OBJECT *Parse_Plane ()
  998.   {
  999.    DBL len;
  1000.    PLANE *Object;
  1001.  
  1002.    Parse_Begin ();
  1003.  
  1004.    if ( (Object = (PLANE *)Parse_Object_Id()) != NULL)
  1005.       return ((OBJECT *) Object);
  1006.  
  1007.    Object = Create_Plane();
  1008.  
  1009.    Parse_Vector(Object->Normal_Vector);   Parse_Comma();
  1010.    VLength(len, Object->Normal_Vector);
  1011.    if (len < EPSILON)
  1012.    {
  1013.      Error("Degenerate plane normal.");
  1014.    }
  1015.    VInverseScaleEq(Object->Normal_Vector, len);
  1016.    Object->Distance = -Parse_Float();
  1017.  
  1018.    Compute_Plane_BBox(Object);
  1019.  
  1020.    Parse_Object_Mods ((OBJECT *)Object);
  1021.  
  1022.    return ((OBJECT *) Object);
  1023.   }
  1024.  
  1025.  
  1026.  
  1027. /*****************************************************************************
  1028. *
  1029. * FUNCTION
  1030. *
  1031. * INPUT
  1032. *   
  1033. * OUTPUT
  1034. *   
  1035. * RETURNS
  1036. *   
  1037. * AUTHOR
  1038. *   
  1039. * DESCRIPTION
  1040. *
  1041. * CHANGES
  1042. *
  1043. ******************************************************************************/
  1044.  
  1045. static
  1046. OBJECT *Parse_HField ()
  1047. {
  1048.   HFIELD *Object;
  1049.   VECTOR Local_Vector;
  1050.   IMAGE *Image;
  1051.  
  1052.   Parse_Begin ();
  1053.  
  1054.   if ( (Object = (HFIELD *)Parse_Object_Id()) != NULL)
  1055.       return ((OBJECT *) Object);
  1056.  
  1057.    Object = Create_HField();
  1058.  
  1059.    Image = Parse_Image (HF_FILE);
  1060.    Image->Use_Colour_Flag = FALSE;
  1061.  
  1062.    Make_Vector(Object->bounding_box->bounds[0], 0.0, 0.0, 0.0);
  1063.  
  1064.    if (Image->File_Type == POT_FILE)
  1065.    {
  1066.      Object->bounding_box->bounds[1][X] = Image->width/2.0 - 1.0;
  1067.    }
  1068.    else
  1069.    {
  1070.      Object->bounding_box->bounds[1][X] = Image->width - 1.0;
  1071.    }
  1072.  
  1073.    Object->bounding_box->bounds[1][Y] = 65536.0;
  1074.    Object->bounding_box->bounds[1][Z] = Image->height - 1.0;
  1075.  
  1076.    Make_Vector(Local_Vector,
  1077.      1.0 / (Object->bounding_box->bounds[1][X]),
  1078.      1.0 / (Object->bounding_box->bounds[1][Y]),
  1079.      1.0 / (Object->bounding_box->bounds[1][Z]));
  1080.  
  1081.    Compute_Scaling_Transform(Object->Trans, Local_Vector);
  1082.  
  1083.    Parse_Object_Mods ((OBJECT *)Object);
  1084.  
  1085.    Compute_HField(Object, Image);
  1086.  
  1087.    Compute_HField_BBox(Object);
  1088.  
  1089.    Destroy_Image (Image);
  1090.  
  1091.    return ((OBJECT *) Object);
  1092.   }
  1093.  
  1094.  
  1095.  
  1096. /*****************************************************************************
  1097. *
  1098. * FUNCTION
  1099. *
  1100. * INPUT
  1101. *   
  1102. * OUTPUT
  1103. *   
  1104. * RETURNS
  1105. *   
  1106. * AUTHOR
  1107. *   
  1108. * DESCRIPTION
  1109. *
  1110. * CHANGES
  1111. *
  1112. ******************************************************************************/
  1113.  
  1114. static OBJECT *Parse_Triangle()
  1115. {
  1116.   TRIANGLE *Object;
  1117.  
  1118.   Parse_Begin();
  1119.  
  1120.   if ((Object = (TRIANGLE *)Parse_Object_Id()) != NULL)
  1121.   {
  1122.     return((OBJECT *) Object);
  1123.   }
  1124.  
  1125.   Object = Create_Triangle();
  1126.  
  1127.   Parse_Vector(Object->P1);    Parse_Comma();
  1128.   Parse_Vector(Object->P2);    Parse_Comma();
  1129.   Parse_Vector(Object->P3);
  1130.  
  1131.   /* Note that Compute_Triangle also computes the bounding box. */
  1132.  
  1133.   if (!Compute_Triangle(Object, FALSE))
  1134.   {
  1135.     Warn(0.0, "Degenerate triangle. Please remove.");
  1136.   }
  1137.  
  1138.   Parse_Object_Mods((OBJECT *)Object);
  1139.  
  1140.   return((OBJECT *)Object);
  1141. }
  1142.  
  1143.  
  1144.  
  1145. /*****************************************************************************
  1146. *
  1147. * FUNCTION
  1148. *
  1149. * INPUT
  1150. *   
  1151. * OUTPUT
  1152. *   
  1153. * RETURNS
  1154. *   
  1155. * AUTHOR
  1156. *   
  1157. * DESCRIPTION
  1158. *
  1159. * CHANGES
  1160. *
  1161. ******************************************************************************/
  1162.  
  1163. static
  1164. OBJECT *Parse_Smooth_Triangle ()
  1165.   {
  1166.    SMOOTH_TRIANGLE *Object;
  1167.    short degen;
  1168.    DBL vlen;
  1169.  
  1170.    degen=FALSE;
  1171.  
  1172.    Parse_Begin ();
  1173.  
  1174.    if ( (Object = (SMOOTH_TRIANGLE *)Parse_Object_Id()) != NULL)
  1175.       return ((OBJECT *) Object);
  1176.  
  1177.    Object = Create_Smooth_Triangle();
  1178.  
  1179.    Parse_Vector (Object->P1);    Parse_Comma();
  1180.    Parse_Vector (Object->N1);    Parse_Comma();
  1181.  
  1182.    VLength(vlen,Object->N1);
  1183.  
  1184.    if (vlen == 0.0)
  1185.      degen=TRUE;
  1186.    else
  1187.      VNormalize (Object->N1, Object->N1);
  1188.  
  1189.    Parse_Vector (Object->P2);    Parse_Comma();
  1190.    Parse_Vector (Object->N2);    Parse_Comma();
  1191.  
  1192.    VLength(vlen,Object->N2);
  1193.  
  1194.    if (vlen == 0.0)
  1195.      degen=TRUE;
  1196.    else
  1197.      VNormalize (Object->N2, Object->N2);
  1198.  
  1199.    Parse_Vector (Object->P3);    Parse_Comma();
  1200.    Parse_Vector (Object->N3);
  1201.  
  1202.    VLength(vlen,Object->N3);
  1203.  
  1204.    if (vlen == 0.0)
  1205.      degen=TRUE;
  1206.    else
  1207.      VNormalize (Object->N3, Object->N3);
  1208.  
  1209.    if (!degen)
  1210.    {
  1211.      degen=!Compute_Triangle ((TRIANGLE *) Object,TRUE);
  1212.    }
  1213.  
  1214.    if (degen)
  1215.    {
  1216.      Warn(0.0, "Degenerate triangle. Please remove.");
  1217.    }
  1218.  
  1219.    Compute_Triangle_BBox((TRIANGLE *)Object);
  1220.  
  1221.    Parse_Object_Mods ((OBJECT *)Object);
  1222.  
  1223.    return ((OBJECT *) Object);
  1224.  }
  1225.  
  1226.  
  1227.  
  1228. /*****************************************************************************
  1229. *
  1230. * FUNCTION
  1231. *
  1232. * INPUT
  1233. *   
  1234. * OUTPUT
  1235. *   
  1236. * RETURNS
  1237. *   
  1238. * AUTHOR
  1239. *   
  1240. * DESCRIPTION
  1241. *
  1242. * CHANGES
  1243. *
  1244. ******************************************************************************/
  1245.  
  1246. static
  1247. OBJECT *Parse_Quadric ()
  1248.   {
  1249.    VECTOR Min, Max;
  1250.    QUADRIC *Object;
  1251.  
  1252.    Parse_Begin ();
  1253.  
  1254.    if ( (Object = (QUADRIC *)Parse_Object_Id()) != NULL)
  1255.       return ((OBJECT *) Object);
  1256.  
  1257.    Object = Create_Quadric();
  1258.  
  1259.         Parse_Vector(Object->Square_Terms);     Parse_Comma();
  1260.         Parse_Vector(Object->Mixed_Terms);      Parse_Comma();
  1261.         Parse_Vector(Object->Terms);            Parse_Comma();
  1262.    Object->Constant = Parse_Float();
  1263.  
  1264.    Make_Vector(Min, -BOUND_HUGE, -BOUND_HUGE, -BOUND_HUGE);
  1265.    Make_Vector(Max,  BOUND_HUGE,  BOUND_HUGE,  BOUND_HUGE);
  1266.  
  1267.    Compute_Quadric_BBox(Object, Min, Max);  
  1268.  
  1269.    Parse_Object_Mods ((OBJECT *)Object);
  1270.  
  1271.    return ((OBJECT *) Object);
  1272.   }
  1273.  
  1274.  
  1275.  
  1276. /*****************************************************************************
  1277. *
  1278. * FUNCTION
  1279. *
  1280. * INPUT
  1281. *   
  1282. * OUTPUT
  1283. *   
  1284. * RETURNS
  1285. *   
  1286. * AUTHOR
  1287. *   
  1288. * DESCRIPTION
  1289. *
  1290. * CHANGES
  1291. *
  1292. ******************************************************************************/
  1293.  
  1294. static
  1295. OBJECT *Parse_Box ()
  1296.   {
  1297.    BOX *Object;
  1298.    DBL temp;
  1299.  
  1300.    Parse_Begin ();
  1301.  
  1302.    if ( (Object = (BOX *)Parse_Object_Id()) != NULL)
  1303.       return ((OBJECT *) Object);
  1304.  
  1305.    Object = Create_Box();
  1306.  
  1307.         Parse_Vector(Object->bounds[0]);     Parse_Comma();
  1308.         Parse_Vector(Object->bounds[1]);
  1309.  
  1310.     if (Object->bounds[0][X] > Object->bounds[1][X]) {
  1311.        temp = Object->bounds[0][X];
  1312.        Object->bounds[0][X] = Object->bounds[1][X];
  1313.        Object->bounds[1][X] = temp;
  1314.        }
  1315.     if (Object->bounds[0][Y] > Object->bounds[1][Y]) {
  1316.        temp = Object->bounds[0][Y];
  1317.        Object->bounds[0][Y] = Object->bounds[1][Y];
  1318.        Object->bounds[1][Y] = temp;
  1319.        }
  1320.     if (Object->bounds[0][Z] > Object->bounds[1][Z]) {
  1321.        temp = Object->bounds[0][Z];
  1322.        Object->bounds[0][Z] = Object->bounds[1][Z];
  1323.        Object->bounds[1][Z] = temp;
  1324.        }
  1325.  
  1326.    Compute_Box_BBox(Object);
  1327.  
  1328.    Parse_Object_Mods ((OBJECT *)Object);
  1329.  
  1330.    return ((OBJECT *) Object);
  1331.   }
  1332.  
  1333.  
  1334.  
  1335. /*****************************************************************************
  1336. *
  1337. * FUNCTION
  1338. *
  1339. * INPUT
  1340. *   
  1341. * OUTPUT
  1342. *   
  1343. * RETURNS
  1344. *   
  1345. * AUTHOR
  1346. *   
  1347. * DESCRIPTION
  1348. *
  1349. * CHANGES
  1350. *
  1351. ******************************************************************************/
  1352.  
  1353. static
  1354. OBJECT *Parse_Disc ()
  1355.   {
  1356.    DISC *Object;
  1357.    DBL tmpf;
  1358.  
  1359.    Parse_Begin ();
  1360.  
  1361.    if ( (Object = (DISC *)Parse_Object_Id()) != NULL)
  1362.       return ((OBJECT *) Object);
  1363.  
  1364.    Object = Create_Disc();
  1365.  
  1366.         Parse_Vector(Object->center); Parse_Comma ();
  1367.         Parse_Vector(Object->normal); Parse_Comma ();
  1368.    VNormalize(Object->normal, Object->normal);
  1369.  
  1370.    tmpf = Parse_Float(); Parse_Comma ();
  1371.    Object->oradius2 = tmpf * tmpf;
  1372.  
  1373.    EXPECT
  1374.      CASE_FLOAT
  1375.        tmpf = Parse_Float();
  1376.        Object->iradius2 = tmpf * tmpf;
  1377.      END_CASE
  1378.  
  1379.      OTHERWISE
  1380.        UNGET
  1381.        EXIT
  1382.      END_CASE
  1383.    END_EXPECT
  1384.  
  1385.    /* Calculate info needed for ray-disc intersections */
  1386.    VDot(tmpf, Object->center, Object->normal);
  1387.    Object->d = -tmpf;
  1388.  
  1389.    Compute_Disc(Object);  
  1390.  
  1391.    Parse_Object_Mods ((OBJECT *)Object);
  1392.  
  1393.    return ((OBJECT *) Object);
  1394.   }
  1395.  
  1396.  
  1397.  
  1398. /*****************************************************************************
  1399. *
  1400. * FUNCTION
  1401. *
  1402. * INPUT
  1403. *   
  1404. * OUTPUT
  1405. *   
  1406. * RETURNS
  1407. *   
  1408. * AUTHOR
  1409. *   
  1410. * DESCRIPTION
  1411. *
  1412. * CHANGES
  1413. *
  1414. ******************************************************************************/
  1415.  
  1416. static
  1417. OBJECT *Parse_Cylinder ()
  1418.   {
  1419.    CONE *Object;
  1420.  
  1421.    Parse_Begin ();
  1422.  
  1423.    if ( (Object = (CONE *)Parse_Object_Id()) != NULL)
  1424.       return ((OBJECT *) Object);
  1425.  
  1426.    Object = Create_Cylinder();
  1427.  
  1428.         Parse_Vector(Object->apex);  Parse_Comma ();
  1429.         Parse_Vector(Object->base);  Parse_Comma ();
  1430.    Object->apex_radius = Parse_Float();
  1431.    Object->base_radius = Object->apex_radius;
  1432.  
  1433.    EXPECT
  1434.      CASE(OPEN_TOKEN)
  1435.        Clear_Flag(Object, CLOSED_FLAG);
  1436.        EXIT
  1437.      END_CASE
  1438.  
  1439.      OTHERWISE
  1440.        UNGET
  1441.        EXIT
  1442.      END_CASE
  1443.    END_EXPECT
  1444.  
  1445.    Compute_Cylinder_Data((OBJECT *)Object);
  1446.  
  1447.    Compute_Cone_BBox(Object);
  1448.  
  1449.    Parse_Object_Mods ((OBJECT *)Object);
  1450.  
  1451.    return ((OBJECT *) Object);
  1452.   }
  1453.  
  1454.  
  1455.  
  1456. /*****************************************************************************
  1457. *
  1458. * FUNCTION
  1459. *
  1460. * INPUT
  1461. *   
  1462. * OUTPUT
  1463. *   
  1464. * RETURNS
  1465. *   
  1466. * AUTHOR
  1467. *   
  1468. * DESCRIPTION
  1469. *
  1470. * CHANGES
  1471. *
  1472. ******************************************************************************/
  1473.  
  1474. static
  1475. OBJECT *Parse_Cone ()
  1476.   {
  1477.    CONE *Object;
  1478.  
  1479.    Parse_Begin ();
  1480.  
  1481.    if ( (Object = (CONE *)Parse_Object_Id()) != NULL)
  1482.       return ((OBJECT *) Object);
  1483.  
  1484.    Object = Create_Cone();
  1485.  
  1486.         Parse_Vector(Object->apex);  Parse_Comma ();
  1487.         Object->apex_radius = Parse_Float();  Parse_Comma ();
  1488.  
  1489.         Parse_Vector(Object->base);  Parse_Comma ();
  1490.    Object->base_radius = Parse_Float();
  1491.  
  1492.    EXPECT
  1493.      CASE(OPEN_TOKEN)
  1494.        Clear_Flag(Object, CLOSED_FLAG);
  1495.        EXIT
  1496.      END_CASE
  1497.      
  1498.      OTHERWISE
  1499.        UNGET
  1500.        EXIT
  1501.      END_CASE
  1502.    END_EXPECT
  1503.  
  1504.    /* Compute run-time values for the cone */
  1505.    Compute_Cone_Data((OBJECT *)Object);
  1506.  
  1507.    Compute_Cone_BBox(Object);  
  1508.  
  1509.    Parse_Object_Mods ((OBJECT *)Object);
  1510.  
  1511.    return ((OBJECT *) Object);
  1512.   }
  1513.  
  1514.  
  1515.  
  1516. /*****************************************************************************
  1517. *
  1518. * FUNCTION
  1519. *
  1520. *   Parse_Blob_Element_Mods
  1521. *
  1522. * INPUT
  1523. *   
  1524. * OUTPUT
  1525. *   
  1526. * RETURNS
  1527. *   
  1528. * AUTHOR
  1529. *
  1530. *   Dieter Bayer
  1531. *   
  1532. * DESCRIPTION
  1533. *
  1534. *   -
  1535. *
  1536. * CHANGES
  1537. *
  1538. *   Sep 1994 : Creation.
  1539. *
  1540. ******************************************************************************/
  1541.  
  1542. static void Parse_Blob_Element_Mods(Element)
  1543. BLOB_ELEMENT *Element;
  1544. {
  1545.   VECTOR Local_Vector;
  1546.   MATRIX Local_Matrix;
  1547.   TRANSFORM Local_Trans;
  1548.   TEXTURE *Local_Texture;
  1549.  
  1550.   EXPECT
  1551.     CASE (TRANSLATE_TOKEN)
  1552.       Parse_Vector (Local_Vector);
  1553.       Translate_Blob_Element (Element, Local_Vector);
  1554.     END_CASE
  1555.  
  1556.     CASE (ROTATE_TOKEN)
  1557.       Parse_Vector (Local_Vector);
  1558.       Rotate_Blob_Element (Element, Local_Vector);
  1559.     END_CASE
  1560.  
  1561.     CASE (SCALE_TOKEN)
  1562.       Parse_Scale_Vector (Local_Vector);
  1563.       Scale_Blob_Element (Element, Local_Vector);
  1564.     END_CASE
  1565.  
  1566.     CASE (TRANSFORM_TOKEN)
  1567.       GET(TRANSFORM_ID_TOKEN)
  1568.       Transform_Blob_Element (Element, (TRANSFORM *)Token.Constant_Data);
  1569.     END_CASE
  1570.  
  1571.     CASE (MATRIX_TOKEN)
  1572.       Parse_Matrix (Local_Matrix);
  1573.       Compute_Matrix_Transform(&Local_Trans, Local_Matrix);
  1574.       Transform_Blob_Element (Element, &Local_Trans);
  1575.     END_CASE
  1576.  
  1577.     CASE (TEXTURE_TOKEN)
  1578.       Parse_Begin ();
  1579.       Local_Texture = Parse_Texture();
  1580.       Parse_End ();
  1581.       Link_Textures(&Element->Texture, Local_Texture);
  1582.     END_CASE
  1583.  
  1584.     CASE4 (PIGMENT_TOKEN, TNORMAL_TOKEN, FINISH_TOKEN, HALO_TOKEN)
  1585.       if (Element->Texture == NULL)
  1586.       {
  1587.         Element->Texture = Copy_Textures(Default_Texture);
  1588.       }
  1589.       else
  1590.       {
  1591.         if (Element->Texture->Type != PLAIN_PATTERN)
  1592.         {
  1593.           Link_Textures(&Element->Texture, Copy_Textures(Default_Texture));
  1594.         }
  1595.       }
  1596.       UNGET
  1597.       EXPECT
  1598.         CASE (PIGMENT_TOKEN)
  1599.           Parse_Begin ();
  1600.           Parse_Pigment(&Element->Texture->Pigment);
  1601.           Parse_End ();
  1602.         END_CASE
  1603.  
  1604.         CASE (TNORMAL_TOKEN)
  1605.           Parse_Begin ();
  1606.           Parse_Tnormal(&Element->Texture->Tnormal);
  1607.           Parse_End ();
  1608.         END_CASE
  1609.  
  1610.         CASE (FINISH_TOKEN)
  1611.           Parse_Finish(&Element->Texture->Finish);
  1612.         END_CASE
  1613.  
  1614.         CASE (HALO_TOKEN)
  1615.           Parse_Halo(&(Element->Texture->Halo));
  1616.         END_CASE
  1617.  
  1618.         OTHERWISE
  1619.           UNGET
  1620.           EXIT
  1621.         END_CASE
  1622.       END_EXPECT
  1623.     END_CASE
  1624.  
  1625.     OTHERWISE
  1626.       UNGET
  1627.       EXIT
  1628.     END_CASE
  1629.   END_EXPECT
  1630.  
  1631.   Parse_End();
  1632.  
  1633.   /* Postprocess to make sure that HAS_FILTER will be set correctly. */
  1634.  
  1635.   Post_Textures(Element->Texture);
  1636. }
  1637.  
  1638.  
  1639.  
  1640. /*****************************************************************************
  1641. *
  1642. * FUNCTION
  1643. *
  1644. *   Parse_Blob
  1645. *
  1646. * INPUT
  1647. *
  1648. * OUTPUT
  1649. *   
  1650. * RETURNS
  1651. *   
  1652. * AUTHOR
  1653. *
  1654. *   Dieter Bayer
  1655. *   
  1656. * DESCRIPTION
  1657. *
  1658. *   -
  1659. *
  1660. * CHANGES
  1661. *
  1662. *   Jul 1994 : Creation.
  1663. *
  1664. ******************************************************************************/
  1665.  
  1666. static OBJECT *Parse_Blob()
  1667. {
  1668.   int npoints;
  1669.   DBL threshold;
  1670.   VECTOR Axis, Base, Apex;
  1671.   BLOB *Object;
  1672.   blobstackptr blob_components, blob_component;
  1673.  
  1674.   Parse_Begin();
  1675.  
  1676.   if ((Object = (BLOB *)Parse_Object_Id()) != NULL)
  1677.   {
  1678.     return ((OBJECT *) Object);
  1679.   }
  1680.  
  1681.   Object = Create_Blob();
  1682.  
  1683.   blob_components = NULL;
  1684.  
  1685.   npoints = 0;
  1686.  
  1687.   threshold = 1.0;
  1688.  
  1689.   EXPECT
  1690.     CASE (THRESHOLD_TOKEN)
  1691.       threshold = Parse_Float();
  1692.     END_CASE
  1693.  
  1694.     /*************************************************************************
  1695.      * Read sperical component (old syntax).
  1696.      *************************************************************************/
  1697.  
  1698.     CASE (COMPONENT_TOKEN)
  1699.       blob_component = Create_Blob_List_Element();
  1700.  
  1701.       blob_component->elem.Type = BLOB_SPHERE;
  1702.  
  1703.       blob_component->elem.c[2] = Parse_Float();
  1704.  
  1705.       Parse_Comma();
  1706.  
  1707.       blob_component->elem.rad2 = Parse_Float();
  1708.  
  1709.       Parse_Comma();
  1710.  
  1711.       blob_component->elem.rad2 = Sqr(blob_component->elem.rad2);
  1712.  
  1713.       Parse_Vector(blob_component->elem.O);
  1714.  
  1715.       /* Next component. */
  1716.  
  1717.       blob_component->next = blob_components;
  1718.  
  1719.       blob_components = blob_component;
  1720.  
  1721.       npoints++;
  1722.     END_CASE
  1723.  
  1724.     /*************************************************************************
  1725.      * Read sperical component (new syntax).
  1726.      *************************************************************************/
  1727.  
  1728.     CASE (SPHERE_TOKEN)
  1729.       blob_component = Create_Blob_List_Element();
  1730.  
  1731.       blob_component->elem.Type = BLOB_SPHERE;
  1732.  
  1733.       Parse_Begin();
  1734.  
  1735.       Parse_Vector(blob_component->elem.O);
  1736.  
  1737.       Parse_Comma();
  1738.  
  1739.       blob_component->elem.rad2 = Parse_Float();
  1740.  
  1741.       blob_component->elem.rad2 = Sqr(blob_component->elem.rad2);
  1742.  
  1743.       Parse_Comma();
  1744.  
  1745.       ALLOW(STRENGTH_TOKEN)
  1746.  
  1747.       blob_component->elem.c[2] = Parse_Float();
  1748.  
  1749.       Parse_Blob_Element_Mods(&blob_component->elem);
  1750.  
  1751.       /* Next component. */
  1752.  
  1753.       blob_component->next = blob_components;
  1754.  
  1755.       blob_components = blob_component;
  1756.  
  1757.       npoints++;
  1758.     END_CASE
  1759.  
  1760.     /*************************************************************************
  1761.      * Read cylindrical component.
  1762.      *************************************************************************/
  1763.  
  1764.     CASE (CYLINDER_TOKEN)
  1765.       blob_component = Create_Blob_List_Element();
  1766.  
  1767.       blob_component->elem.Type = BLOB_CYLINDER;
  1768.  
  1769.       blob_component->elem.Trans = Create_Transform();
  1770.  
  1771.       Parse_Begin();
  1772.  
  1773.       Parse_Vector(Base);
  1774.  
  1775.       Parse_Comma();
  1776.  
  1777.       Parse_Vector(Apex);
  1778.  
  1779.       Parse_Comma();
  1780.  
  1781.       blob_component->elem.rad2 = Parse_Float();
  1782.  
  1783.       blob_component->elem.rad2 = Sqr(blob_component->elem.rad2);
  1784.  
  1785.       Parse_Comma();
  1786.  
  1787.       ALLOW(STRENGTH_TOKEN)
  1788.  
  1789.       blob_component->elem.c[2] = Parse_Float();
  1790.  
  1791.       /* Calculate cylinder's coordinate system. */
  1792.  
  1793.       VSub(Axis, Apex, Base);
  1794.  
  1795.       VLength(blob_component->elem.len, Axis);
  1796.  
  1797.       if (blob_component->elem.len < EPSILON)
  1798.       {
  1799.         Error("Degenerate cylindrical component in blob.\n");
  1800.       }
  1801.  
  1802.       VInverseScaleEq(Axis, blob_component->elem.len);
  1803.  
  1804.       Compute_Coordinate_Transform(blob_component->elem.Trans, Base, Axis, 1.0, 1.0);
  1805.  
  1806.       Parse_Blob_Element_Mods(&blob_component->elem);
  1807.  
  1808.       /* Next component. */
  1809.  
  1810.       blob_component->next = blob_components;
  1811.  
  1812.       blob_components = blob_component;
  1813.  
  1814.       npoints++;
  1815.     END_CASE
  1816.  
  1817.     OTHERWISE
  1818.       UNGET
  1819.       EXIT
  1820.     END_CASE
  1821.   END_EXPECT
  1822.  
  1823.   Create_Blob_Element_Texture_List(Object, blob_components, npoints);
  1824.  
  1825.   Parse_Object_Mods((OBJECT *)Object);
  1826.  
  1827.   /* The blob's texture has to be processed before Make_Blob() is called. */
  1828.  
  1829.   Post_Textures(Object->Texture);
  1830.   
  1831.   /* Finally, process the information */
  1832.  
  1833.   Make_Blob(Object, threshold, blob_components, npoints);
  1834.  
  1835.   return((OBJECT *)Object);
  1836. }
  1837.  
  1838.  
  1839.  
  1840. /*****************************************************************************
  1841. *
  1842. * FUNCTION
  1843. *
  1844. *   Parse_Julia_Fractal
  1845. *
  1846. * INPUT None
  1847. *   
  1848. * OUTPUT Fractal Objecstructure filledt
  1849. *   
  1850. * RETURNS 
  1851. *
  1852. *   OBJECT * -
  1853. *   
  1854. * AUTHOR
  1855. *
  1856. *   Pascal Massimino
  1857. *   
  1858. * DESCRIPTION
  1859. *
  1860. *   -
  1861. *
  1862. * CHANGES
  1863. *
  1864. *   Dec 1994 : Adopted to version 3.0. [DB]
  1865. *   Sept 1995 : Total rewrite for new syntax [TW]
  1866. *
  1867. ******************************************************************************/
  1868.  
  1869. static OBJECT *Parse_Julia_Fractal ()
  1870. {
  1871.   FRACTAL *Object;
  1872.   DBL P;
  1873.  
  1874.   Parse_Begin();
  1875.  
  1876.   if ( (Object = (FRACTAL *)Parse_Object_Id()) != NULL)
  1877.     return((OBJECT *)Object);
  1878.  
  1879.   Object = Create_Fractal();
  1880.  
  1881.   Parse_Vector4D(Object->Julia_Parm); 
  1882.  
  1883.   EXPECT
  1884.  
  1885.     CASE(MAX_ITERATION_TOKEN)
  1886.       Object->n = (int)floor(Parse_Float()); 
  1887.  
  1888.       if (Object->n <= 0)
  1889.       {
  1890.         Object->n = 1;
  1891.       }
  1892.     END_CASE
  1893.  
  1894.     CASE(SLICE_TOKEN)
  1895.       Parse_Vector4D(Object->Slice);
  1896.       Parse_Comma();
  1897.       Object->SliceDist = Parse_Float(); 
  1898.  
  1899.       /* normalize slice vector */
  1900.       V4D_Dot(P,Object->Slice, Object->Slice);
  1901.       if (fabs(P) < EPSILON)
  1902.       {
  1903.         Error("Slice vector is zero.\n");
  1904.       }
  1905.       if (fabs(Object->Slice[T]) < EPSILON)
  1906.       {
  1907.         Error("Slice t component is zero.\n");
  1908.       }
  1909.       P = sqrt(P);
  1910.       V4D_InverseScaleEq(Object->Slice, P);      
  1911.  
  1912.     END_CASE
  1913.  
  1914.     CASE(PRECISION_TOKEN)
  1915.       P = Parse_Float(); 
  1916.       if ( P < 1.0 )
  1917.       {
  1918.         P = 1.0;
  1919.       }
  1920.       Object->Precision = 1.0 / P;
  1921.     END_CASE
  1922.       
  1923.     CASE(FLOAT_FUNCT_TOKEN)
  1924.       switch(Token.Function_Id)
  1925.       {
  1926.         case EXP_TOKEN:
  1927.           Object->Sub_Type = EXP_STYPE;
  1928.           break;
  1929.         case LOG_TOKEN:
  1930.           Object->Sub_Type = LOG_STYPE;
  1931.           break;
  1932.         case SIN_TOKEN:
  1933.           Object->Sub_Type = SIN_STYPE;
  1934.           break;
  1935.         case ASIN_TOKEN:
  1936.           Object->Sub_Type = ASIN_STYPE;
  1937.           break;
  1938.         case COS_TOKEN:
  1939.           Object->Sub_Type = COS_STYPE;
  1940.           break;
  1941.         case ACOS_TOKEN:
  1942.           Object->Sub_Type = ACOS_STYPE;
  1943.           break;
  1944.         default: Parse_Error_Str ("fractal keyword");
  1945.       }    
  1946.     END_CASE
  1947.  
  1948.     /* if any of the next become supported by the expression parser,
  1949.      * then their handling would need to move above to the FUNC_TOKEN
  1950.      * case above.
  1951.      */
  1952.     CASE(ATAN_TOKEN)
  1953.       Object->Sub_Type = ATAN_STYPE;
  1954.     END_CASE
  1955.  
  1956.     CASE(COSH_TOKEN)
  1957.       Object->Sub_Type = COSH_STYPE;
  1958.     END_CASE
  1959.  
  1960.     CASE(SINH_TOKEN)
  1961.       Object->Sub_Type = SINH_STYPE;
  1962.     END_CASE
  1963.  
  1964.     CASE(TANH_TOKEN)
  1965.       Object->Sub_Type = TANH_STYPE;
  1966.     END_CASE
  1967.  
  1968.     CASE(ATANH_TOKEN)
  1969.       Object->Sub_Type = ATANH_STYPE;
  1970.     END_CASE
  1971.  
  1972.     CASE(ACOSH_TOKEN)
  1973.       Object->Sub_Type = ACOSH_STYPE;
  1974.     END_CASE
  1975.  
  1976.     CASE(ASINH_TOKEN)
  1977.       Object->Sub_Type = ASINH_STYPE;
  1978.     END_CASE
  1979.  
  1980.     CASE(SQR_TOKEN)
  1981.       Object->Sub_Type = SQR_STYPE;
  1982.     END_CASE
  1983.  
  1984.     CASE(PWR_TOKEN)
  1985.       Object->Sub_Type = PWR_STYPE;
  1986.       Parse_Float_Param2(&Object->exponent.x,&Object->exponent.y);
  1987.     END_CASE
  1988.  
  1989.     CASE(CUBE_TOKEN)
  1990.       Object->Sub_Type = CUBE_STYPE;
  1991.     END_CASE
  1992.  
  1993.     CASE(RECIPROCAL_TOKEN)
  1994.       Object->Sub_Type = RECIPROCAL_STYPE;
  1995.     END_CASE
  1996.  
  1997.     CASE(HYPERCOMPLEX_TOKEN)
  1998.       Object->Algebra = HYPERCOMPLEX_TYPE;
  1999.     END_CASE
  2000.  
  2001.     CASE(QUATERNION_TOKEN)
  2002.       Object->Algebra = QUATERNION_TYPE;
  2003.     END_CASE
  2004.  
  2005.     OTHERWISE
  2006.       UNGET
  2007.       EXIT
  2008.     END_CASE
  2009.  
  2010.   END_EXPECT
  2011.  
  2012.   Parse_Object_Mods((OBJECT *)Object);
  2013.  
  2014.   SetUp_Fractal(Object);
  2015.  
  2016.   return((OBJECT *)Object);
  2017. }
  2018.  
  2019.  
  2020.  
  2021.  
  2022. /*****************************************************************************
  2023. *
  2024. * FUNCTION
  2025. *
  2026. *   Parse_Polygon
  2027. *
  2028. * INPUT
  2029. *
  2030. * OUTPUT
  2031. *
  2032. * RETURNS
  2033. *
  2034. *   OBJECT * -
  2035. *
  2036. * AUTHOR
  2037. *
  2038. *   Dieter Bayer
  2039. *   
  2040. * DESCRIPTION
  2041. *
  2042. *   -
  2043. *
  2044. * CHANGES
  2045. *
  2046. *   May 1994 : Creation.
  2047. *
  2048. *   Oct 1994 : Modified to use new polygon data structure. [DB]
  2049. *
  2050. ******************************************************************************/
  2051.  
  2052. static OBJECT *Parse_Polygon()
  2053. {
  2054.   int i, closed = FALSE;
  2055.   int Number;
  2056.   POLYGON *Object;
  2057.   VECTOR *Points, P;
  2058.  
  2059.   Parse_Begin();
  2060.  
  2061.   if ((Object = (POLYGON *)Parse_Object_Id()) != NULL)
  2062.   {
  2063.     return((OBJECT *) Object);
  2064.   }
  2065.  
  2066.   Object = Create_Polygon();
  2067.  
  2068.   Number = (int)Parse_Float();
  2069.  
  2070.   if (Number < 3)
  2071.   {
  2072.     Error("Polygon needs at least three points.");
  2073.   }
  2074.  
  2075.   Points = (VECTOR *)POV_MALLOC((Number+1)*sizeof(VECTOR), "temporary polygon points");
  2076.  
  2077.   for (i = 0; i < Number; i++)
  2078.   {
  2079.     Parse_Comma();
  2080.  
  2081.     Parse_Vector(Points[i]);
  2082.   }
  2083.  
  2084.   /* Check for closed polygons. */
  2085.  
  2086.   Assign_Vector(P, Points[0]);
  2087.  
  2088.   for (i = 1; i < Number; i++)
  2089.   {
  2090.     closed = FALSE;
  2091.  
  2092.     if ((fabs(P[X] - Points[i][X]) < EPSILON) &&
  2093.         (fabs(P[Y] - Points[i][Y]) < EPSILON) &&
  2094.         (fabs(P[Z] - Points[i][Z]) < EPSILON))
  2095.     {
  2096.       i++;
  2097.  
  2098.       if (i < Number)
  2099.       {
  2100.         Assign_Vector(P, Points[i]);
  2101.       }
  2102.  
  2103.       closed = TRUE;
  2104.     }
  2105.   }
  2106.  
  2107.   if (!closed)
  2108.   {
  2109.     Warn(0.0, "Polygon not closed. Closing it.");
  2110.  
  2111.     Assign_Vector(Points[Number], P);
  2112.  
  2113.     Number++;
  2114.   }
  2115.  
  2116.   Compute_Polygon(Object, Number, Points);
  2117.  
  2118.   POV_FREE (Points);
  2119.  
  2120.   Parse_Object_Mods ((OBJECT *)Object);
  2121.  
  2122.   return((OBJECT *) Object);
  2123. }
  2124.  
  2125.  
  2126.  
  2127. /*****************************************************************************
  2128. *
  2129. * FUNCTION
  2130. *
  2131. *   Parse_Prism
  2132. *
  2133. * INPUT
  2134. *
  2135. * OUTPUT
  2136. *
  2137. * RETURNS
  2138. *
  2139. *   OBJECT * -
  2140. *
  2141. * AUTHOR
  2142. *
  2143. *   Dieter Bayer
  2144. *
  2145. * DESCRIPTION
  2146. *
  2147. *   -
  2148. *
  2149. * CHANGES
  2150. *
  2151. *   May 1994 : Creation.
  2152. *
  2153. ******************************************************************************/
  2154.  
  2155. static OBJECT *Parse_Prism()
  2156. {
  2157.   int i, closed = FALSE;
  2158.   DBL h;
  2159.  
  2160.   PRISM *Object;
  2161.   UV_VECT *Points, P;
  2162.  
  2163.   Parse_Begin();
  2164.  
  2165.   if ((Object = (PRISM *)Parse_Object_Id()) != NULL)
  2166.   {
  2167.     return((OBJECT *) Object);
  2168.   }
  2169.  
  2170.   Object = Create_Prism();
  2171.  
  2172.   /* 
  2173.    * Determine kind of spline used (linear, quadratic, cubic) 
  2174.    * and type of sweeping (linear, conic).
  2175.    */
  2176.  
  2177.   EXPECT
  2178.     CASE(LINEAR_SPLINE_TOKEN)
  2179.       Object->Spline_Type = LINEAR_SPLINE;
  2180.     END_CASE
  2181.  
  2182.     CASE(QUADRATIC_SPLINE_TOKEN)
  2183.       Object->Spline_Type = QUADRATIC_SPLINE;
  2184.     END_CASE
  2185.  
  2186.     CASE(CUBIC_SPLINE_TOKEN)
  2187.       Object->Spline_Type = CUBIC_SPLINE;
  2188.     END_CASE
  2189.  
  2190.     CASE(LINEAR_SWEEP_TOKEN)
  2191.       Object->Sweep_Type = LINEAR_SWEEP;
  2192.     END_CASE
  2193.  
  2194.     CASE(CONIC_SWEEP_TOKEN)
  2195.       Object->Sweep_Type = CONIC_SWEEP;
  2196.     END_CASE
  2197.  
  2198.     OTHERWISE
  2199.       UNGET
  2200.       EXIT
  2201.     END_CASE
  2202.   END_EXPECT
  2203.  
  2204.   /* Read prism heights. */
  2205.  
  2206.   Object->Height1 = Parse_Float(); Parse_Comma();
  2207.   Object->Height2 = Parse_Float(); Parse_Comma();
  2208.  
  2209.   if (Object->Height1 > Object->Height2)
  2210.   {
  2211.     h = Object->Height1;
  2212.     Object->Height1 = Object->Height2;
  2213.     Object->Height2 = h;
  2214.   }
  2215.  
  2216.   /* Get number of points = number of segments. */
  2217.  
  2218.   Object->Number = (int)Parse_Float();
  2219.  
  2220.   switch (Object->Spline_Type)
  2221.   {
  2222.     case LINEAR_SPLINE :
  2223.  
  2224.       if (Object->Number < 3)
  2225.       {
  2226.         Error("Prism with linear splines must have at least three points.");
  2227.       }
  2228.  
  2229.       break;
  2230.  
  2231.     case QUADRATIC_SPLINE :
  2232.  
  2233.       if (Object->Number < 5)
  2234.       {
  2235.         Error("Prism with quadratic splines must have at least five points.");
  2236.       }
  2237.  
  2238.       break;
  2239.  
  2240.     case CUBIC_SPLINE :
  2241.  
  2242.       if (Object->Number < 6)
  2243.       {
  2244.         Error("Prism with cubic splines must have at least six points.");
  2245.       }
  2246.   }
  2247.  
  2248.   /* Allocate Object->Number points for the prism. */
  2249.  
  2250.   Points = (UV_VECT *)POV_MALLOC((Object->Number+1) * sizeof(UV_VECT), "temporary prism points");
  2251.  
  2252.   /* Read points (x, y : coordinate of 2d point; z : not used). */
  2253.  
  2254.   for (i = 0; i < Object->Number; i++)
  2255.   {
  2256.     Parse_Comma();
  2257.  
  2258.     Parse_UV_Vect(Points[i]);
  2259.   }
  2260.  
  2261.   /* Closed or not closed that's the question. */
  2262.  
  2263.   EXPECT
  2264.     CASE(OPEN_TOKEN)
  2265.       Clear_Flag(Object, CLOSED_FLAG);
  2266.       EXIT
  2267.     END_CASE
  2268.  
  2269.     OTHERWISE
  2270.       UNGET
  2271.       EXIT
  2272.     END_CASE
  2273.   END_EXPECT
  2274.  
  2275.   /* Check for closed prism. */
  2276.  
  2277.   switch (Object->Spline_Type)
  2278.   {
  2279.     case LINEAR_SPLINE :
  2280.  
  2281.       i = 1;
  2282.  
  2283.       Assign_UV_Vect(P, Points[0]);
  2284.  
  2285.       break;
  2286.  
  2287.     case QUADRATIC_SPLINE :
  2288.     case CUBIC_SPLINE :
  2289.  
  2290.       i = 2;
  2291.  
  2292.       Assign_UV_Vect(P, Points[1]);
  2293.  
  2294.       break;
  2295.   }
  2296.  
  2297.   for ( ; i < Object->Number; i++)
  2298.   {
  2299.     closed = FALSE;
  2300.  
  2301.     if ((fabs(P[X] - Points[i][X]) < EPSILON) &&
  2302.         (fabs(P[Y] - Points[i][Y]) < EPSILON))
  2303.     {
  2304.       switch (Object->Spline_Type)
  2305.       {
  2306.         case LINEAR_SPLINE :
  2307.  
  2308.           i++;
  2309.  
  2310.           if (i < Object->Number)
  2311.           {
  2312.             Assign_UV_Vect(P, Points[i]);
  2313.           }
  2314.  
  2315.           break;
  2316.  
  2317.         case QUADRATIC_SPLINE :
  2318.  
  2319.           i += 2;
  2320.  
  2321.           if (i < Object->Number)
  2322.           {
  2323.             Assign_UV_Vect(P, Points[i]);
  2324.           }
  2325.  
  2326.           break;
  2327.  
  2328.         case CUBIC_SPLINE :
  2329.  
  2330.           i += 3;
  2331.  
  2332.           if (i < Object->Number)
  2333.           {
  2334.             Assign_UV_Vect(P, Points[i]);
  2335.           }
  2336.  
  2337.           break;
  2338.       }
  2339.  
  2340.       closed = TRUE;
  2341.     }
  2342.   }
  2343.  
  2344.   if (!closed)
  2345.   {
  2346.     if (Object->Spline_Type == LINEAR_SPLINE)
  2347.     {
  2348.       Assign_UV_Vect(Points[Object->Number], P);
  2349.  
  2350.       Object->Number++;
  2351.  
  2352.       Warn(0.0, "Linear prism not closed. Closing it.");
  2353.     }
  2354.     else
  2355.     {
  2356.       Set_Flag(Object, DEGENERATE_FLAG);
  2357.  
  2358.       Warn(0.0, "Prism not closed. Ignoring it.");
  2359.     }
  2360.   }
  2361.  
  2362.   /* Compute spline segments. */
  2363.  
  2364.   Compute_Prism(Object, Points);
  2365.  
  2366.   /* Compute bounding box. */
  2367.  
  2368.   Compute_Prism_BBox(Object);
  2369.  
  2370.   /* Parse object's modifiers. */
  2371.  
  2372.   Parse_Object_Mods((OBJECT *)Object);
  2373.  
  2374.   /* Destroy temporary points. */
  2375.  
  2376.   POV_FREE (Points);
  2377.  
  2378.   return((OBJECT *) Object);
  2379. }
  2380.  
  2381.  
  2382.  
  2383. /*****************************************************************************
  2384. *
  2385. * FUNCTION
  2386. *
  2387. *   Parse_Sor
  2388. *
  2389. * INPUT
  2390. *   
  2391. * OUTPUT
  2392. *   
  2393. * RETURNS
  2394. *
  2395. *   OBJECT * -
  2396. *
  2397. * AUTHOR
  2398. *
  2399. *   Dieter Bayer
  2400. *   
  2401. * DESCRIPTION
  2402. *
  2403. *   Read a surface of revolution primitive.
  2404. *
  2405. * CHANGES
  2406. *
  2407. *   May 1994 : Creation.
  2408. *
  2409. ******************************************************************************/
  2410.  
  2411. static OBJECT *Parse_Sor()
  2412. {
  2413.   int i;
  2414.   SOR *Object;
  2415.   UV_VECT *Points;
  2416.  
  2417.   Parse_Begin();
  2418.  
  2419.   if ((Object = (SOR *)Parse_Object_Id()) != NULL)
  2420.   {
  2421.     return((OBJECT *)Object);
  2422.   }
  2423.  
  2424.   Object = Create_Sor();
  2425.  
  2426.   /* Get number of points. */
  2427.  
  2428.   Object->Number = (int)Parse_Float();
  2429.  
  2430.   if (Object->Number <4)
  2431.   {
  2432.     Error("Surface of revolution must have at least four points.");
  2433.   }
  2434.  
  2435.   /* Get temporary points describing the rotated curve. */
  2436.  
  2437.   Points = (UV_VECT *)POV_MALLOC(Object->Number*sizeof(UV_VECT), "temporary surface of revolution points");
  2438.  
  2439.   /* Read points (x : radius; y : height; z : not used). */
  2440.  
  2441.   for (i = 0; i < Object->Number; i++)
  2442.   {
  2443.     Parse_Comma();
  2444.  
  2445.     Parse_UV_Vect(Points[i]);
  2446.  
  2447.     if ((Points[i][X] < 0.0) ||
  2448.         ((i > 1 ) && (i < Object->Number - 1) && (Points[i][Y] <= Points[i-1][Y])))
  2449.     {
  2450.       Error("Incorrect point in surface of revolution.");
  2451.     }
  2452.   }
  2453.  
  2454.   /* Closed or not closed that's the question. */
  2455.  
  2456.   EXPECT
  2457.     CASE(OPEN_TOKEN)
  2458.       Clear_Flag(Object, CLOSED_FLAG);
  2459.       EXIT
  2460.     END_CASE
  2461.  
  2462.     OTHERWISE
  2463.       UNGET
  2464.       EXIT
  2465.     END_CASE
  2466.   END_EXPECT
  2467.  
  2468.   /* There are Number-3 segments! */
  2469.  
  2470.   Object->Number -= 3;
  2471.  
  2472.   /* Compute spline segments. */
  2473.  
  2474.   Compute_Sor(Object, Points);
  2475.  
  2476.   /* Compute bounding box. */
  2477.  
  2478.   Compute_Sor_BBox(Object);
  2479.  
  2480.   /* Parse object's modifiers. */
  2481.  
  2482.   Parse_Object_Mods((OBJECT *)Object);
  2483.  
  2484.   /* Destroy temporary points. */
  2485.  
  2486.   POV_FREE (Points);
  2487.  
  2488.   return ((OBJECT *) Object);
  2489. }
  2490.  
  2491.  
  2492.  
  2493. /*****************************************************************************
  2494. *
  2495. * FUNCTION
  2496. *
  2497. *   Parse_Lathe
  2498. *
  2499. * INPUT
  2500. *   
  2501. * OUTPUT
  2502. *   
  2503. * RETURNS
  2504. *
  2505. *   OBJECT * -
  2506. *   
  2507. * AUTHOR
  2508. *
  2509. *   Dieter Bayer
  2510. *   
  2511. * DESCRIPTION
  2512. *
  2513. *   Read a lathe primitive.
  2514. *
  2515. * CHANGES
  2516. *
  2517. *   Jun 1994 : Creation.
  2518. *
  2519. ******************************************************************************/
  2520.  
  2521. static OBJECT *Parse_Lathe()
  2522. {
  2523.   int i;
  2524.   LATHE *Object;
  2525.   UV_VECT *Points;
  2526.  
  2527.   Parse_Begin();
  2528.  
  2529.   if ((Object = (LATHE *)Parse_Object_Id()) != NULL)
  2530.   {
  2531.     return((OBJECT *)Object);
  2532.   }
  2533.  
  2534.   Object = Create_Lathe();
  2535.  
  2536.   /* Determine kind of spline used and aspect ratio. */
  2537.  
  2538.   EXPECT
  2539.     CASE(LINEAR_SPLINE_TOKEN)
  2540.       Object->Spline_Type = LINEAR_SPLINE;
  2541.     END_CASE
  2542.  
  2543.     CASE(QUADRATIC_SPLINE_TOKEN)
  2544.       Object->Spline_Type = QUADRATIC_SPLINE;
  2545.     END_CASE
  2546.  
  2547.     CASE(CUBIC_SPLINE_TOKEN)
  2548.       Object->Spline_Type = CUBIC_SPLINE;
  2549.     END_CASE
  2550.  
  2551.     OTHERWISE
  2552.       UNGET
  2553.       EXIT
  2554.     END_CASE
  2555.   END_EXPECT
  2556.  
  2557.   /* Get number of points. */
  2558.  
  2559.   Object->Number = (int)Parse_Float();
  2560.  
  2561.   /* Get temporary points describing the rotated curve. */
  2562.  
  2563.   Points = (UV_VECT *)POV_MALLOC(Object->Number*sizeof(UV_VECT), "temporary lathe points");
  2564.  
  2565.   /* Read points (x : radius; y : height; z : not used). */
  2566.  
  2567.   for (i = 0; i < Object->Number; i++)
  2568.   {
  2569.     Parse_Comma();
  2570.  
  2571.     Parse_UV_Vect(Points[i]);
  2572.  
  2573.     if (Points[i][X] < 0.0)
  2574.     {
  2575.       Error("Incorrect point in lathe.");
  2576.     }
  2577.   }
  2578.  
  2579.   switch (Object->Spline_Type)
  2580.   {
  2581.     case LINEAR_SPLINE :
  2582.  
  2583.       Object->Number--;
  2584.  
  2585.       break;
  2586.  
  2587.     case QUADRATIC_SPLINE :
  2588.  
  2589.       Object->Number -= 2;
  2590.  
  2591.       break;
  2592.  
  2593.     case CUBIC_SPLINE :
  2594.  
  2595.       Object->Number -= 3;
  2596.  
  2597.       break;
  2598.   }
  2599.  
  2600.   if (Object->Number <1)
  2601.   {
  2602.     Error("Lathe must have at least one segment.");
  2603.   }
  2604.  
  2605.   /* Compute spline segments. */
  2606.  
  2607.   Compute_Lathe(Object, Points);
  2608.  
  2609.   /* Compute bounding box. */
  2610.  
  2611.   Compute_Lathe_BBox(Object);
  2612.  
  2613.   /* Parse object's modifiers. */
  2614.  
  2615.   Parse_Object_Mods((OBJECT *)Object);
  2616.  
  2617.   /* Destroy temporary points. */
  2618.  
  2619.   POV_FREE (Points);
  2620.  
  2621.   return((OBJECT *) Object);
  2622. }
  2623.  
  2624.  
  2625.  
  2626. /*****************************************************************************
  2627. *
  2628. * FUNCTION
  2629. *
  2630. *   Parse_Superellipsoid
  2631. *
  2632. * INPUT
  2633. *   
  2634. * OUTPUT
  2635. *   
  2636. * RETURNS
  2637. *
  2638. *   OBJECT * -
  2639. *   
  2640. * AUTHOR
  2641. *
  2642. *   Dieter Bayer
  2643. *   
  2644. * DESCRIPTION
  2645. *
  2646. *   Read a superellipsoid primitive.
  2647. *
  2648. * CHANGES
  2649. *
  2650. *   Oct 1994 : Creation.
  2651. *
  2652. ******************************************************************************/
  2653.  
  2654. static OBJECT *Parse_Superellipsoid()
  2655. {
  2656.   UV_VECT V1;
  2657.   SUPERELLIPSOID *Object;
  2658.  
  2659.   Parse_Begin();
  2660.  
  2661.   if ((Object = (SUPERELLIPSOID *)Parse_Object_Id()) != NULL)
  2662.   {
  2663.     return((OBJECT *)Object);
  2664.   }
  2665.  
  2666.   Object = Create_Superellipsoid();
  2667.  
  2668.   Parse_UV_Vect(V1);
  2669.  
  2670.   /* The x component is e, the y component is n. */
  2671.  
  2672.   Object->Power[X] = 2.0  / V1[X];
  2673.   Object->Power[Y] = V1[X] / V1[Y];
  2674.   Object->Power[Z] = 2.0  / V1[Y];
  2675.  
  2676.   /* Compute bounding box. */
  2677.  
  2678.   Compute_Superellipsoid_BBox(Object);
  2679.  
  2680.   /* Parse object's modifiers. */
  2681.  
  2682.   Parse_Object_Mods((OBJECT *)Object);
  2683.  
  2684.   return((OBJECT *) Object);
  2685. }
  2686.  
  2687.  
  2688. /*****************************************************************************
  2689. *
  2690. * FUNCTION
  2691. *
  2692. *   Parse_Torus
  2693. *
  2694. * INPUT
  2695. *   
  2696. * OUTPUT
  2697. *   
  2698. * RETURNS
  2699. *
  2700. *   OBJECT
  2701. *
  2702. * AUTHOR
  2703. *
  2704. *   Dieter Bayer
  2705. *   
  2706. * DESCRIPTION
  2707. *
  2708. *   -
  2709. *
  2710. * CHANGES
  2711. *
  2712. *   Jul 1994 : Creation.
  2713. *
  2714. ******************************************************************************/
  2715.  
  2716. static OBJECT *Parse_Torus()
  2717. {
  2718.   TORUS *Object;
  2719.  
  2720.   Parse_Begin();
  2721.  
  2722.   if ((Object = (TORUS *)Parse_Object_Id()) != NULL)
  2723.   {
  2724.     return((OBJECT *)Object);
  2725.   }
  2726.  
  2727.   Object = Create_Torus();
  2728.  
  2729.   /* Read in the two radii. */
  2730.  
  2731.   Object->R = Parse_Float(); /* Big radius */
  2732.  
  2733.   Parse_Comma();
  2734.  
  2735.   Object->r = Parse_Float(); /* Little radius */
  2736.  
  2737.   Compute_Torus_BBox(Object);
  2738.  
  2739.   Parse_Object_Mods ((OBJECT *)Object);
  2740.  
  2741.   return ((OBJECT *) Object);
  2742. }
  2743.  
  2744.  
  2745.  
  2746. /*****************************************************************************
  2747. *
  2748. * FUNCTION
  2749. *
  2750. *   Parse_Mesh_Texture
  2751. *
  2752. * INPUT
  2753. *   
  2754. * OUTPUT
  2755. *   
  2756. * RETURNS
  2757. *
  2758. *   OBJECT
  2759. *   
  2760. * AUTHOR
  2761. *
  2762. *   Dieter Bayer
  2763. *   
  2764. * DESCRIPTION
  2765. *
  2766. *   Read an individual triangle mesh texture.
  2767. *
  2768. * CHANGES
  2769. *
  2770. *   Feb 1995 : Creation.
  2771. *
  2772. ******************************************************************************/
  2773.  
  2774. static TEXTURE *Parse_Mesh_Texture()
  2775. {
  2776.   TEXTURE *Texture;
  2777.  
  2778.   Texture = NULL;
  2779.  
  2780.   EXPECT
  2781.     CASE(TEXTURE_TOKEN)
  2782.       Parse_Begin();
  2783.  
  2784.       GET(TEXTURE_ID_TOKEN);
  2785.  
  2786.       Texture = (TEXTURE *)Token.Constant_Data;
  2787.  
  2788.       Parse_End();
  2789.     END_CASE
  2790.  
  2791.     OTHERWISE
  2792.       UNGET
  2793.       EXIT
  2794.     END_CASE
  2795.   END_EXPECT
  2796.  
  2797.   return(Texture);
  2798. }
  2799.  
  2800.  
  2801.  
  2802. /*****************************************************************************
  2803. *
  2804. * FUNCTION
  2805. *
  2806. *   Parse_Mesh
  2807. *
  2808. * INPUT
  2809. *   
  2810. * OUTPUT
  2811. *   
  2812. * RETURNS
  2813. *
  2814. *   OBJECT
  2815. *   
  2816. * AUTHOR
  2817. *
  2818. *   Dieter Bayer
  2819. *   
  2820. * DESCRIPTION
  2821. *
  2822. *   Read a triangle mesh.
  2823. *
  2824. * CHANGES
  2825. *
  2826. *   Feb 1995 : Creation.
  2827. *
  2828. ******************************************************************************/
  2829.  
  2830. static OBJECT *Parse_Mesh()
  2831. {
  2832.   int i;
  2833.   int number_of_normals, number_of_textures, number_of_triangles, number_of_vertices;
  2834.   int max_normals, max_textures, max_triangles, max_vertices;
  2835.   DBL l1, l2, l3;
  2836.   VECTOR D1, D2, P1, P2, P3, N1, N2, N3, N;
  2837.   SNGL_VECT *Normals, *Vertices;
  2838.   TEXTURE **Textures;
  2839.   MESH *Object;
  2840.   MESH_TRIANGLE *Triangles;
  2841.  
  2842.   Parse_Begin();
  2843.  
  2844.   if ((Object = (MESH *)Parse_Object_Id()) != NULL)
  2845.   {
  2846.     return((OBJECT *)Object);
  2847.   }
  2848.  
  2849.   /* Create object. */
  2850.  
  2851.   Object = Create_Mesh();
  2852.  
  2853.   /* Allocate temporary normals, textures, triangles and vertices. */
  2854.  
  2855.   max_normals = 256;
  2856.  
  2857.   max_vertices = 256;
  2858.  
  2859.   max_textures = 16;
  2860.  
  2861.   max_triangles = 256;
  2862.  
  2863.   Normals = (SNGL_VECT *)POV_MALLOC(max_normals*sizeof(SNGL_VECT), "temporary triangle mesh data");
  2864.  
  2865.   Textures = (TEXTURE **)POV_MALLOC(max_textures*sizeof(TEXTURE *), "temporary triangle mesh data");
  2866.  
  2867.   Triangles = (MESH_TRIANGLE *)POV_MALLOC(max_triangles*sizeof(MESH_TRIANGLE), "temporary triangle mesh data");
  2868.  
  2869.   Vertices = (SNGL_VECT *)POV_MALLOC(max_vertices*sizeof(SNGL_VECT), "temporary triangle mesh data");
  2870.  
  2871.   /* Read raw triangle file. */
  2872.  
  2873.   number_of_normals = 0;
  2874.  
  2875.   number_of_textures = 0;
  2876.  
  2877.   number_of_triangles = 0;
  2878.  
  2879.   number_of_vertices = 0;
  2880.  
  2881.   /* Create hash tables. */
  2882.  
  2883.   Create_Mesh_Hash_Tables();
  2884.  
  2885.   EXPECT
  2886.     CASE(TRIANGLE_TOKEN)
  2887.       Parse_Begin();
  2888.  
  2889.       Parse_Vector(P1);  Parse_Comma();
  2890.       Parse_Vector(P2);  Parse_Comma();
  2891.       Parse_Vector(P3);
  2892.  
  2893.       if (!Mesh_Degenerate(P1, P2, P3))
  2894.       {
  2895.         if (number_of_triangles >= max_triangles)
  2896.         {
  2897.           if (max_triangles >= INT_MAX/2)
  2898.           {
  2899.             Error("Too many triangles in triangle mesh.\n");
  2900.           }
  2901.  
  2902.           max_triangles *= 2;
  2903.  
  2904.           Triangles = (MESH_TRIANGLE *)POV_REALLOC(Triangles, max_triangles*sizeof(MESH_TRIANGLE), "triangle triangle mesh data");
  2905.         }
  2906.  
  2907.         /* Init triangle. */
  2908.  
  2909.         Init_Mesh_Triangle(&Triangles[number_of_triangles]);
  2910.  
  2911.         Triangles[number_of_triangles].P1 = Mesh_Hash_Vertex(&number_of_vertices, &max_vertices, &Vertices, P1);
  2912.         Triangles[number_of_triangles].P2 = Mesh_Hash_Vertex(&number_of_vertices, &max_vertices, &Vertices, P2);
  2913.         Triangles[number_of_triangles].P3 = Mesh_Hash_Vertex(&number_of_vertices, &max_vertices, &Vertices, P3);
  2914.  
  2915.         Compute_Mesh_Triangle(&Triangles[number_of_triangles], FALSE, P1, P2, P3, N);
  2916.  
  2917.         Triangles[number_of_triangles].Normal_Ind = Mesh_Hash_Normal(&number_of_normals, &max_normals, &Normals, N);
  2918.  
  2919.         Triangles[number_of_triangles].Texture = Mesh_Hash_Texture(&number_of_textures, &max_textures, &Textures, Parse_Mesh_Texture());
  2920.  
  2921.         number_of_triangles++;
  2922.       }
  2923.  
  2924.       Parse_End();
  2925.     END_CASE
  2926.  
  2927.     CASE(SMOOTH_TRIANGLE_TOKEN)
  2928.       Parse_Begin();
  2929.  
  2930.       Parse_Vector(P1);  Parse_Comma();
  2931.       Parse_Vector(N1);  Parse_Comma();
  2932.  
  2933.       Parse_Vector(P2);  Parse_Comma();
  2934.       Parse_Vector(N2);  Parse_Comma();
  2935.  
  2936.       Parse_Vector(P3);  Parse_Comma();
  2937.       Parse_Vector(N3);
  2938.  
  2939.       VLength(l1, N1);
  2940.       VLength(l2, N2);
  2941.       VLength(l3, N3);
  2942.  
  2943.       if ((l1 != 0.0) && (l2 != 0.0) && (l3 != 0.0) && (!Mesh_Degenerate(P1, P2, P3)))
  2944.       {
  2945.         if (number_of_triangles >= max_triangles)
  2946.         {
  2947.           if (max_triangles >= INT_MAX/2)
  2948.           {
  2949.             Error("Too many triangles in triangle mesh.\n");
  2950.           }
  2951.  
  2952.           max_triangles *= 2;
  2953.  
  2954.           Triangles = (MESH_TRIANGLE *)POV_REALLOC(Triangles, max_triangles*sizeof(MESH_TRIANGLE), "triangle triangle mesh data");
  2955.         }
  2956.  
  2957.         VInverseScaleEq(N1, l1);
  2958.         VInverseScaleEq(N2, l2);
  2959.         VInverseScaleEq(N3, l3);
  2960.  
  2961.         /* Init triangle. */
  2962.  
  2963.         Init_Mesh_Triangle(&Triangles[number_of_triangles]);
  2964.  
  2965.         Triangles[number_of_triangles].P1 = Mesh_Hash_Vertex(&number_of_vertices, &max_vertices, &Vertices, P1);
  2966.         Triangles[number_of_triangles].P2 = Mesh_Hash_Vertex(&number_of_vertices, &max_vertices, &Vertices, P2);
  2967.         Triangles[number_of_triangles].P3 = Mesh_Hash_Vertex(&number_of_vertices, &max_vertices, &Vertices, P3);
  2968.  
  2969.         /* Check for equal normals. */
  2970.  
  2971.         VSub(D1, N1, N2);
  2972.         VSub(D2, N1, N3);
  2973.  
  2974.         VDot(l1, D1, D1);
  2975.         VDot(l2, D2, D2);
  2976.  
  2977.         if ((fabs(l1) > EPSILON) && (fabs(l2) > EPSILON))
  2978.         {
  2979.           /* Smooth triangle. */
  2980.  
  2981.           Triangles[number_of_triangles].N1 = Mesh_Hash_Normal(&number_of_normals, &max_normals, &Normals, N1);
  2982.           Triangles[number_of_triangles].N2 = Mesh_Hash_Normal(&number_of_normals, &max_normals, &Normals, N2);
  2983.           Triangles[number_of_triangles].N3 = Mesh_Hash_Normal(&number_of_normals, &max_normals, &Normals, N3);
  2984.  
  2985.           Compute_Mesh_Triangle(&Triangles[number_of_triangles], TRUE, P1, P2, P3, N);
  2986.         }
  2987.         else
  2988.         {
  2989.           /* Flat triangle. */
  2990.  
  2991.           Compute_Mesh_Triangle(&Triangles[number_of_triangles], FALSE, P1, P2, P3, N);
  2992.         }
  2993.  
  2994.         Triangles[number_of_triangles].Normal_Ind = Mesh_Hash_Normal(&number_of_normals, &max_normals, &Normals, N);
  2995.  
  2996.         Triangles[number_of_triangles].Texture = Mesh_Hash_Texture(&number_of_textures, &max_textures, &Textures, Parse_Mesh_Texture());
  2997.  
  2998.         number_of_triangles++;
  2999.       }
  3000.  
  3001.       Parse_End();
  3002.     END_CASE
  3003.  
  3004.     OTHERWISE
  3005.       UNGET
  3006.       EXIT
  3007.     END_CASE
  3008.   END_EXPECT
  3009.  
  3010.   /* Destroy hash tables. */
  3011.  
  3012.   Destroy_Mesh_Hash_Tables();
  3013.  
  3014.   /* If there are no triangles something went wrong. */
  3015.  
  3016.   if (number_of_triangles == 0)
  3017.   {
  3018.     Error("No triangles in triangle mesh.\n");
  3019.   }
  3020.  
  3021.   /* Init triangle mesh data. */
  3022.  
  3023.   Object->Data = POV_MALLOC(sizeof(MESH_DATA), "triangle mesh data");
  3024.  
  3025.   Object->Data->References = 1;
  3026.  
  3027.   Object->Data->Tree = NULL;
  3028.   
  3029.   Object->Data->Normals   = NULL;
  3030.   Object->Data->Textures  = NULL;
  3031.   Object->Data->Triangles = NULL;
  3032.   Object->Data->Vertices  = NULL;
  3033.  
  3034.   /* Allocate memory for normals, textures, triangles and vertices. */
  3035.  
  3036.   Object->Data->Number_Of_Normals = number_of_normals;
  3037.  
  3038.   Object->Data->Number_Of_Textures = number_of_textures;
  3039.  
  3040.   Object->Data->Number_Of_Triangles = number_of_triangles;
  3041.  
  3042.   Object->Data->Number_Of_Vertices = number_of_vertices;
  3043.  
  3044.   Object->Data->Normals = (SNGL_VECT *)POV_MALLOC(number_of_normals*sizeof(SNGL_VECT), "triangle mesh data");
  3045.  
  3046.   if (number_of_textures)
  3047.   {
  3048.     Set_Flag(Object, MULTITEXTURE_FLAG);
  3049.  
  3050.     Object->Data->Textures = (TEXTURE **)POV_MALLOC(number_of_textures*sizeof(TEXTURE *), "triangle mesh data");
  3051.   }
  3052.  
  3053.   Object->Data->Triangles = (MESH_TRIANGLE *)POV_MALLOC(number_of_triangles*sizeof(MESH_TRIANGLE), "triangle mesh data");
  3054.  
  3055.   Object->Data->Vertices = (SNGL_VECT *)POV_MALLOC(number_of_vertices*sizeof(SNGL_VECT), "triangle mesh data");
  3056.  
  3057.   /* Copy normals, textures, triangles and vertices into mesh. */
  3058.  
  3059.   for (i = 0; i < number_of_normals; i++)
  3060.   {
  3061.     Assign_SNGL_Vect(Object->Data->Normals[i], Normals[i]);
  3062.   }
  3063.  
  3064.   for (i = 0; i < number_of_textures; i++)
  3065.   {
  3066.     Object->Data->Textures[i] = Textures[i];
  3067.   }
  3068.  
  3069.   for (i = 0; i < number_of_triangles; i++)
  3070.   {
  3071.     Object->Data->Triangles[i] = Triangles[i];
  3072.   }
  3073.  
  3074.   for (i = 0; i < number_of_vertices; i++)
  3075.   {
  3076.     Assign_SNGL_Vect(Object->Data->Vertices[i], Vertices[i]);
  3077.   }
  3078.  
  3079.   /* Free temporary memory. */
  3080.  
  3081.   POV_FREE(Normals);
  3082.   POV_FREE(Textures);
  3083.   POV_FREE(Triangles);
  3084.   POV_FREE(Vertices);
  3085.  
  3086. /*
  3087.   Render_Info("Mesh: %ld bytes: %ld vertices, %ld normals, %ld textures, %ld triangles\n",
  3088.     Object->Data->Number_Of_Normals*sizeof(SNGL_VECT)+
  3089.     Object->Data->Number_Of_Textures*sizeof(TEXTURE *)+
  3090.     Object->Data->Number_Of_Triangles*sizeof(MESH_TRIANGLE)+
  3091.     Object->Data->Number_Of_Vertices*sizeof(SNGL_VECT),
  3092.     Object->Data->Number_Of_Vertices,
  3093.     Object->Data->Number_Of_Normals,
  3094.     Object->Data->Number_Of_Textures,
  3095.     Object->Data->Number_Of_Triangles);
  3096. */
  3097.  
  3098.   /* Create bounding box. */
  3099.  
  3100.   Compute_Mesh_BBox(Object);
  3101.  
  3102.   /* Parse object modifiers. */
  3103.  
  3104.   Parse_Object_Mods((OBJECT *)Object);
  3105.  
  3106.   /* Create bounding box tree. */
  3107.  
  3108.   Build_Mesh_BBox_Tree(Object);
  3109.  
  3110.   return((OBJECT *)Object);
  3111. }
  3112.  
  3113.  
  3114.  
  3115. /*****************************************************************************
  3116. *
  3117. * FUNCTION
  3118. *
  3119. * INPUT
  3120. *   
  3121. * OUTPUT
  3122. *   
  3123. * RETURNS
  3124. *   
  3125. * AUTHOR
  3126. *   
  3127. * DESCRIPTION
  3128. *
  3129. * CHANGES
  3130. *
  3131. ******************************************************************************/
  3132.  
  3133. static
  3134. OBJECT *Parse_Poly (order)
  3135.   int order;
  3136.   {
  3137.    POLY *Object;
  3138.  
  3139.    Parse_Begin ();
  3140.  
  3141.    if ( (Object = (POLY *)Parse_Object_Id()) != NULL)
  3142.       return ((OBJECT *) Object);
  3143.  
  3144.    if (order == 0)
  3145.      {
  3146.       order = (int)Parse_Float();      Parse_Comma();
  3147.       if (order < 2 || order > MAX_ORDER)
  3148.         Error("Order of poly is out of range.");
  3149.      }
  3150.  
  3151.    Object = Create_Poly(order);
  3152.  
  3153.    Parse_Coeffs(Object->Order, &(Object->Coeffs[0]));
  3154.  
  3155.    Compute_Poly_BBox(Object);
  3156.  
  3157.    Parse_Object_Mods ((OBJECT *)Object);
  3158.  
  3159.    return ((OBJECT *) Object);
  3160.   }
  3161.  
  3162.  
  3163.  
  3164. /*****************************************************************************
  3165. *
  3166. * FUNCTION
  3167. *
  3168. * INPUT
  3169. *   
  3170. * OUTPUT
  3171. *   
  3172. * RETURNS
  3173. *   
  3174. * AUTHOR
  3175. *   
  3176. * DESCRIPTION
  3177. *
  3178. * CHANGES
  3179. *
  3180. ******************************************************************************/
  3181.  
  3182. static
  3183. OBJECT *Parse_Bicubic_Patch ()
  3184.   {
  3185.    BICUBIC_PATCH *Object;
  3186.    int i, j;
  3187.  
  3188.    Parse_Begin ();
  3189.  
  3190.    if ( (Object = (BICUBIC_PATCH *)Parse_Object_Id()) != NULL)
  3191.       return ((OBJECT *) Object);
  3192.  
  3193.    Object = Create_Bicubic_Patch();
  3194.  
  3195.    EXPECT
  3196.      CASE_FLOAT
  3197.        Warn(1.5, "Should use keywords for bicubic parameters.");
  3198.        Object->Patch_Type = (int)Parse_Float();
  3199.        if (Object->Patch_Type == 2 ||
  3200.            Object->Patch_Type == 3)
  3201.            Object->Flatness_Value = Parse_Float();
  3202.          else
  3203.            Object->Flatness_Value = 0.1;
  3204.        Object->U_Steps = (int)Parse_Float();
  3205.        Object->V_Steps = (int)Parse_Float();
  3206.        EXIT
  3207.      END_CASE
  3208.        
  3209.      CASE (TYPE_TOKEN)
  3210.        Object->Patch_Type = (int)Parse_Float();
  3211.      END_CASE
  3212.  
  3213.      CASE (FLATNESS_TOKEN)
  3214.        Object->Flatness_Value = Parse_Float();
  3215.      END_CASE
  3216.  
  3217.      CASE (V_STEPS_TOKEN)
  3218.        Object->V_Steps = (int)Parse_Float();
  3219.      END_CASE
  3220.  
  3221.      CASE (U_STEPS_TOKEN)
  3222.        Object->U_Steps = (int)Parse_Float();
  3223.      END_CASE
  3224.  
  3225.      OTHERWISE
  3226.        UNGET
  3227.        EXIT
  3228.      END_CASE
  3229.    END_EXPECT
  3230.  
  3231.    if (Object->Patch_Type > 1)
  3232.      {
  3233.       Object->Patch_Type = 1;
  3234.       Warn(0.0, "Patch type no longer supported. Using type 1.");
  3235.      }
  3236.  
  3237.    if ((Object->Patch_Type < 0) || (Object->Patch_Type > MAX_PATCH_TYPE))
  3238.      Error("Undefined bicubic patch type.");
  3239.  
  3240.    Parse_Comma();
  3241.    for (i=0;i<4;i++)
  3242.      for (j=0;j<4;j++)
  3243.        {
  3244.                   Parse_Vector(Object->Control_Points[i][j]);
  3245.         if (!((i==3)&&(j==3)))
  3246.           Parse_Comma();
  3247.        };
  3248.    Precompute_Patch_Values(Object); /* interpolated mesh coords */
  3249.  
  3250.    Compute_Bicubic_Patch_BBox(Object);  
  3251.  
  3252.    Parse_Object_Mods ((OBJECT *)Object);
  3253.  
  3254.    return ((OBJECT *) Object);
  3255.   }
  3256.  
  3257.  
  3258.  
  3259. /*****************************************************************************
  3260. *
  3261. * FUNCTION
  3262. *
  3263. * INPUT
  3264. *   
  3265. * OUTPUT
  3266. *   
  3267. * RETURNS
  3268. *   
  3269. * AUTHOR
  3270. *   
  3271. * DESCRIPTION
  3272. *
  3273. * CHANGES
  3274. *
  3275. ******************************************************************************/
  3276.  
  3277. static
  3278. OBJECT *Parse_TrueType ()
  3279.   {
  3280.    OBJECT *Object;
  3281.    char *filename, *text_string;
  3282.    DBL depth;
  3283.    VECTOR offset;
  3284.  
  3285.    Parse_Begin ();
  3286.    
  3287.    GET(TTF_TOKEN);
  3288.  
  3289.    if ( (Object = (OBJECT *)Parse_Object_Id()) != NULL)
  3290.       return ((OBJECT *) Object);
  3291.       
  3292.    Object = (OBJECT *)Create_CSG_Union ();
  3293.    /*** Object = Create_TTF(); */
  3294.  
  3295.    /* Parse the TrueType font file name */
  3296.    filename = Parse_String();
  3297.    Parse_Comma();
  3298.  
  3299.    /* Parse the text string to be rendered */
  3300.    text_string = Parse_String();
  3301.    Parse_Comma();
  3302.  
  3303.    /* Get the extrusion depth */
  3304.    depth = Parse_Float(); Parse_Comma ();
  3305.  
  3306.    /* Get the offset vector */
  3307.    Parse_Vector(offset);
  3308.  
  3309.    /* Process all this good info */
  3310.    ProcessNewTTF((OBJECT *)Object, filename, text_string, depth, offset);
  3311.  
  3312.    /* Free up the filename and text string memory */
  3313.    POV_FREE (filename);
  3314.    POV_FREE (text_string);
  3315.  
  3316.    /**** Compute_TTF_BBox(Object); */
  3317.    Compute_CSG_BBox((OBJECT *)Object);
  3318.  
  3319.    /* Get any rotate/translate or texturing stuff */
  3320.    Parse_Object_Mods ((OBJECT *)Object);
  3321.  
  3322.    return ((OBJECT *) Object);
  3323.   }
  3324.  
  3325.  
  3326.  
  3327. /*****************************************************************************
  3328. *
  3329. * FUNCTION
  3330. *
  3331. * INPUT
  3332. *   
  3333. * OUTPUT
  3334. *   
  3335. * RETURNS
  3336. *   
  3337. * AUTHOR
  3338. *   
  3339. * DESCRIPTION
  3340. *
  3341. * CHANGES
  3342. *
  3343. ******************************************************************************/
  3344.  
  3345. static
  3346. OBJECT *Parse_CSG (CSG_Type)
  3347.   int CSG_Type;
  3348.   {
  3349.    CSG *Object;
  3350.    OBJECT *Local;
  3351.    int Object_Count = 0;
  3352.  
  3353.    Parse_Begin ();
  3354.  
  3355.    if ( (Object = (CSG *)Parse_Object_Id()) != NULL)
  3356.       return ((OBJECT *) Object);
  3357.  
  3358.    if (CSG_Type & CSG_UNION_TYPE)
  3359.      Object = Create_CSG_Union ();
  3360.    else
  3361.      if (CSG_Type & CSG_MERGE_TYPE)
  3362.        Object = Create_CSG_Merge ();
  3363.      else
  3364.        Object = Create_CSG_Intersection ();
  3365.  
  3366.    Object->Children = NULL;
  3367.  
  3368.    while ((Local = Parse_Object ()) != NULL)
  3369.      {
  3370.       if ((CSG_Type & CSG_INTERSECTION_TYPE) && (Local->Type & PATCH_OBJECT))
  3371.         Warn(0.0, "Patch objects not allowed in intersection.");
  3372.       Object_Count++;
  3373.       if ((CSG_Type & CSG_DIFFERENCE_TYPE) && (Object_Count > 1))
  3374.         Invert_Object (Local);
  3375.       Object->Type |=  (Local->Type & CHILDREN_FLAGS);
  3376.       Local->Type |= IS_CHILD_OBJECT;
  3377.       Link(Local, &Local->Sibling, &Object->Children);
  3378.      };
  3379.  
  3380.    if ((Object_Count < 2) && (opts.Language_Version >= 1.5))
  3381.      Warn(1.5, "Should have at least 2 objects in csg.");
  3382.  
  3383.    Compute_CSG_BBox((OBJECT *)Object);
  3384.  
  3385.    Parse_Object_Mods ((OBJECT *)Object);
  3386.  
  3387.    return ((OBJECT *) Object);
  3388.   }
  3389.  
  3390.  
  3391.  
  3392. /*****************************************************************************
  3393. *
  3394. * FUNCTION
  3395. *
  3396. * INPUT
  3397. *
  3398. * OUTPUT
  3399. *
  3400. * RETURNS
  3401. *
  3402. * AUTHOR
  3403. *
  3404. * DESCRIPTION
  3405. *
  3406. * CHANGES
  3407. *
  3408. ******************************************************************************/
  3409.  
  3410. static
  3411. OBJECT *Parse_Light_Source ()
  3412.   {
  3413.    DBL Len;
  3414.    VECTOR Local_Vector;
  3415.    MATRIX Local_Matrix;
  3416.    TRANSFORM Local_Trans;
  3417.    LIGHT_SOURCE *Object;
  3418.  
  3419.    Parse_Begin ();
  3420.  
  3421.    if ( (Object = (LIGHT_SOURCE *)Parse_Object_Id()) != NULL)
  3422.       return ((OBJECT *) Object);
  3423.       
  3424.    Object = Create_Light_Source ();
  3425.  
  3426.    Parse_Vector(Object->Center);
  3427.  
  3428.    Parse_Comma();
  3429.  
  3430.    Parse_Colour (Object->Colour);
  3431.  
  3432.    EXPECT
  3433.      CASE (LOOKS_LIKE_TOKEN)
  3434.        if (Object->Children != NULL)
  3435.          Error("Only one looks_like allowed per light_source.");
  3436.        Parse_Begin ();
  3437.        Object->Type &= ~(int)PATCH_OBJECT;
  3438.        if ((Object->Children = Parse_Object ()) == NULL)
  3439.          Parse_Error_Str ("object");
  3440.        Compute_Translation_Transform(&Local_Trans, Object->Center);
  3441.        Translate_Object (Object->Children, Object->Center, &Local_Trans);
  3442.        Parse_Object_Mods (Object->Children);
  3443.        Set_Flag(Object->Children, NO_SHADOW_FLAG);
  3444.        Set_Flag(Object, NO_SHADOW_FLAG);
  3445.        Object->Type |= (Object->Children->Type & CHILDREN_FLAGS);
  3446.      END_CASE
  3447.  
  3448.      CASE (FILL_LIGHT_TOKEN)
  3449.        Object->Light_Type = FILL_LIGHT_SOURCE;
  3450.      END_CASE
  3451.  
  3452.      CASE (SPOTLIGHT_TOKEN)
  3453.        Object->Light_Type = SPOT_SOURCE;
  3454.      END_CASE
  3455.  
  3456.      CASE (CYLINDER_TOKEN)
  3457.        Object->Light_Type = CYLINDER_SOURCE;
  3458.      END_CASE
  3459.  
  3460.      CASE (POINT_AT_TOKEN)
  3461.        if ((Object->Light_Type == SPOT_SOURCE) || (Object->Light_Type == CYLINDER_SOURCE))
  3462.          Parse_Vector(Object->Points_At);
  3463.        else
  3464.          Not_With ("point_at","standard light source");
  3465.      END_CASE
  3466.  
  3467.      CASE (TIGHTNESS_TOKEN)
  3468.        if ((Object->Light_Type == SPOT_SOURCE) || (Object->Light_Type == CYLINDER_SOURCE))
  3469.          Object->Coeff = Parse_Float();
  3470.        else
  3471.          Not_With ("tightness","standard light source");
  3472.      END_CASE
  3473.  
  3474.      CASE (RADIUS_TOKEN)
  3475.        if ((Object->Light_Type == SPOT_SOURCE) || (Object->Light_Type == CYLINDER_SOURCE))
  3476.          Object->Radius = Parse_Float();
  3477.        else
  3478.          Not_With ("radius","standard light source");
  3479.      END_CASE
  3480.  
  3481.      CASE (FALLOFF_TOKEN)
  3482.        if ((Object->Light_Type == SPOT_SOURCE) || (Object->Light_Type == CYLINDER_SOURCE))
  3483.          Object->Falloff = Parse_Float();
  3484.        else
  3485.          Not_With ("falloff","standard light source");
  3486.      END_CASE
  3487.  
  3488.      CASE (FADE_DISTANCE_TOKEN)
  3489.        Object->Fade_Distance = Parse_Float();
  3490.      END_CASE
  3491.  
  3492.      CASE (FADE_POWER_TOKEN)
  3493.        Object->Fade_Power = Parse_Float();
  3494.      END_CASE
  3495.  
  3496.      CASE (AREA_LIGHT_TOKEN)
  3497.        Object->Area_Light = TRUE;
  3498.        Parse_Vector (Object->Axis1); Parse_Comma ();
  3499.        Parse_Vector (Object->Axis2); Parse_Comma ();
  3500.        Object->Area_Size1 = (int)Parse_Float(); Parse_Comma ();
  3501.        Object->Area_Size2 = (int)Parse_Float();
  3502.        Object->Light_Grid = Create_Light_Grid (Object->Area_Size1, Object->Area_Size2);
  3503.      END_CASE
  3504.  
  3505.      CASE (JITTER_TOKEN)
  3506.        Object->Jitter = TRUE;
  3507.      END_CASE
  3508.  
  3509.      CASE (TRACK_TOKEN)
  3510.        Object->Track = TRUE;
  3511.      END_CASE
  3512.  
  3513.      CASE (ADAPTIVE_TOKEN)
  3514.        Object->Adaptive_Level = (int)Parse_Float();
  3515.      END_CASE
  3516.  
  3517.      CASE (ATMOSPHERIC_ATTENUATION_TOKEN)
  3518.        Object->Atmospheric_Attenuation = Allow_Float(1.0) > 0.0;
  3519.      END_CASE
  3520.  
  3521.      CASE (ATMOSPHERE_TOKEN)
  3522.        Object->Atmosphere_Interaction = Allow_Float(1.0) > 0.0;
  3523.      END_CASE
  3524.  
  3525.      CASE (TRANSLATE_TOKEN)
  3526.        Parse_Vector (Local_Vector);
  3527.        Compute_Translation_Transform(&Local_Trans, Local_Vector);
  3528.        Translate_Object ((OBJECT *)Object, Local_Vector, &Local_Trans);
  3529.      END_CASE
  3530.  
  3531.      CASE (ROTATE_TOKEN)
  3532.        Parse_Vector (Local_Vector);
  3533.        Compute_Rotation_Transform(&Local_Trans, Local_Vector);
  3534.        Rotate_Object ((OBJECT *)Object, Local_Vector, &Local_Trans);
  3535.      END_CASE
  3536.  
  3537.      CASE (SCALE_TOKEN)
  3538.        Parse_Scale_Vector (Local_Vector);
  3539.        Compute_Scaling_Transform(&Local_Trans, Local_Vector);
  3540.        Scale_Object ((OBJECT *)Object, Local_Vector, &Local_Trans);
  3541.      END_CASE
  3542.  
  3543.      CASE (TRANSFORM_TOKEN)
  3544.        GET(TRANSFORM_ID_TOKEN)
  3545.        Transform_Object ((OBJECT *)Object, (TRANSFORM *)Token.Constant_Data);
  3546.      END_CASE
  3547.  
  3548.      CASE (MATRIX_TOKEN)
  3549.        Parse_Matrix (Local_Matrix);
  3550.        Compute_Matrix_Transform(&Local_Trans, Local_Matrix);
  3551.        Transform_Object ((OBJECT *)Object, &Local_Trans);
  3552.      END_CASE
  3553.  
  3554.      OTHERWISE
  3555.        UNGET
  3556.        EXIT
  3557.      END_CASE
  3558.    END_EXPECT
  3559.  
  3560.    Parse_End ();
  3561.  
  3562.    if (Object->Light_Type == SPOT_SOURCE)
  3563.    {
  3564.      Object->Radius  = cos(Object->Radius * M_PI / 180.0);
  3565.      Object->Falloff = cos(Object->Falloff * M_PI / 180.0);
  3566.    }
  3567.  
  3568.    VSub(Object->Direction, Object->Points_At, Object->Center);
  3569.  
  3570.    VLength(Len, Object->Direction);
  3571.  
  3572.    if (Len > EPSILON)
  3573.    {
  3574.      VInverseScaleEq(Object->Direction, Len);
  3575.    }
  3576.  
  3577.    return ((OBJECT *)Object);
  3578.   }
  3579.  
  3580.  
  3581.  
  3582. /*****************************************************************************
  3583. *
  3584. * FUNCTION
  3585. *
  3586. * INPUT
  3587. *   
  3588. * OUTPUT
  3589. *   
  3590. * RETURNS
  3591. *   
  3592. * AUTHOR
  3593. *   
  3594. * DESCRIPTION
  3595. *
  3596. * CHANGES
  3597. *
  3598. ******************************************************************************/
  3599.  
  3600. OBJECT *Parse_Object ()
  3601.   {
  3602.    OBJECT *Object = NULL;
  3603.  
  3604.    EXPECT
  3605.  
  3606.      CASE (JULIA_FRACTAL_TOKEN)
  3607.        Object = Parse_Julia_Fractal ();
  3608.        EXIT
  3609.      END_CASE
  3610.  
  3611.      CASE (SPHERE_TOKEN)
  3612.        Object = Parse_Sphere ();
  3613.        EXIT
  3614.      END_CASE
  3615.  
  3616.      CASE (PLANE_TOKEN)
  3617.        Object = Parse_Plane ();
  3618.        EXIT
  3619.      END_CASE
  3620.  
  3621.      CASE (CONE_TOKEN)
  3622.        Object = Parse_Cone ();
  3623.        EXIT
  3624.      END_CASE
  3625.  
  3626.      CASE (CYLINDER_TOKEN)
  3627.        Object = Parse_Cylinder ();
  3628.        EXIT
  3629.      END_CASE
  3630.  
  3631.      CASE (DISC_TOKEN)
  3632.        Object = Parse_Disc ();
  3633.        EXIT
  3634.      END_CASE
  3635.  
  3636.      CASE (QUADRIC_TOKEN)
  3637.        Object = Parse_Quadric ();
  3638.        EXIT
  3639.      END_CASE
  3640.  
  3641.      CASE (CUBIC_TOKEN)
  3642.        Object = Parse_Poly (3);
  3643.        EXIT
  3644.      END_CASE
  3645.  
  3646.      CASE (QUARTIC_TOKEN)
  3647.        Object = Parse_Poly (4);
  3648.        EXIT
  3649.      END_CASE
  3650.  
  3651.      CASE (POLY_TOKEN)
  3652.        Object = Parse_Poly (0);
  3653.        EXIT
  3654.      END_CASE
  3655.  
  3656.      CASE (TORUS_TOKEN)
  3657.        Object = Parse_Torus ();
  3658.        EXIT
  3659.      END_CASE
  3660.  
  3661.      /* Parse lathe primitive. [DB 8/94] */
  3662.  
  3663.      CASE (LATHE_TOKEN)
  3664.        Object = Parse_Lathe();
  3665.        EXIT
  3666.      END_CASE
  3667.  
  3668.      /* Parse polygon primitive. [DB 8/94] */
  3669.  
  3670.      CASE (POLYGON_TOKEN)
  3671.        Object = Parse_Polygon();
  3672.        EXIT
  3673.      END_CASE
  3674.  
  3675.      /* Parse prism primitive. [DB 8/94] */
  3676.  
  3677.      CASE (PRISM_TOKEN)
  3678.        Object = Parse_Prism();
  3679.        EXIT
  3680.      END_CASE
  3681.  
  3682.      /* Parse surface of revolution primitive. [DB 8/94] */
  3683.  
  3684.      CASE (SOR_TOKEN)
  3685.        Object = Parse_Sor();
  3686.        EXIT
  3687.      END_CASE
  3688.  
  3689.      /* Parse superellipsoid primitive. [DB 11/94] */
  3690.  
  3691.      CASE (SUPERELLIPSOID_TOKEN)
  3692.        Object = Parse_Superellipsoid();
  3693.        EXIT
  3694.      END_CASE
  3695.  
  3696.      /* Parse triangle mesh primitive. [DB 2/95] */
  3697.  
  3698.      CASE (MESH_TOKEN)
  3699.        Object = Parse_Mesh();
  3700.        EXIT
  3701.      END_CASE
  3702.  
  3703.      CASE (TEXT_TOKEN)
  3704.        Object = Parse_TrueType ();
  3705.        EXIT
  3706.      END_CASE
  3707.  
  3708.      CASE (OBJECT_ID_TOKEN)
  3709.        Object = Copy_Object((OBJECT *) Token.Constant_Data);
  3710.        EXIT
  3711.      END_CASE
  3712.  
  3713.      CASE (UNION_TOKEN)
  3714.        Object = Parse_CSG (CSG_UNION_TYPE);
  3715.        EXIT
  3716.      END_CASE
  3717.  
  3718.      CASE (COMPOSITE_TOKEN)
  3719.        Warn(1.5, "Use union instead of composite.");
  3720.        Object = Parse_CSG (CSG_UNION_TYPE);
  3721.        EXIT
  3722.      END_CASE
  3723.  
  3724.      CASE (MERGE_TOKEN)
  3725.        Object = Parse_CSG (CSG_MERGE_TYPE);
  3726.        EXIT
  3727.      END_CASE
  3728.  
  3729.      CASE (INTERSECTION_TOKEN)
  3730.        Object = Parse_CSG (CSG_INTERSECTION_TYPE);
  3731.        EXIT
  3732.      END_CASE
  3733.  
  3734.      CASE (DIFFERENCE_TOKEN)
  3735.        Object = Parse_CSG (CSG_DIFFERENCE_TYPE+CSG_INTERSECTION_TYPE);
  3736.        EXIT
  3737.      END_CASE
  3738.  
  3739.      CASE (BICUBIC_PATCH_TOKEN)
  3740.        Object = Parse_Bicubic_Patch ();
  3741.        EXIT
  3742.      END_CASE
  3743.  
  3744.      CASE (TRIANGLE_TOKEN)
  3745.        Object = Parse_Triangle ();
  3746.        EXIT
  3747.      END_CASE
  3748.  
  3749.      CASE (SMOOTH_TRIANGLE_TOKEN)
  3750.        Object = Parse_Smooth_Triangle ();
  3751.        EXIT
  3752.      END_CASE
  3753.  
  3754.      CASE (HEIGHT_FIELD_TOKEN)
  3755.        Object = Parse_HField ();
  3756.        EXIT
  3757.      END_CASE
  3758.  
  3759.      CASE (BOX_TOKEN)
  3760.        Object = Parse_Box ();
  3761.        EXIT
  3762.      END_CASE
  3763.  
  3764.      CASE (BLOB_TOKEN)
  3765.        Object = Parse_Blob ();
  3766.        EXIT
  3767.      END_CASE
  3768.  
  3769.      CASE (LIGHT_SOURCE_TOKEN)
  3770.        Object = Parse_Light_Source ();
  3771.        EXIT
  3772.      END_CASE
  3773.  
  3774.      CASE (OBJECT_TOKEN)
  3775.        Parse_Begin ();
  3776.        Object = Parse_Object ();
  3777.        if (!Object)
  3778.          Parse_Error_Str ("object");
  3779.        Parse_Object_Mods ((OBJECT *)Object);
  3780.        EXIT
  3781.      END_CASE
  3782.  
  3783.      OTHERWISE
  3784.        UNGET
  3785.        EXIT
  3786.      END_CASE
  3787.    END_EXPECT
  3788.  
  3789.    return ((OBJECT *) Object);
  3790.   }
  3791.   
  3792.  
  3793.  
  3794. /*****************************************************************************
  3795. *
  3796. * FUNCTION
  3797. *
  3798. * INPUT
  3799. *   
  3800. * OUTPUT
  3801. *   
  3802. * RETURNS
  3803. *   
  3804. * AUTHOR
  3805. *   
  3806. * DESCRIPTION
  3807. *
  3808. * CHANGES
  3809. *
  3810. ******************************************************************************/
  3811.  
  3812. void Parse_Default ()
  3813.   {
  3814.    TEXTURE *Local_Texture;
  3815.    PIGMENT *Local_Pigment;
  3816.    TNORMAL *Local_Tnormal;
  3817.    FINISH  *Local_Finish;
  3818.    HALO    *Local_Halo;
  3819.  
  3820.    Not_In_Default = FALSE;
  3821.    Parse_Begin();
  3822.    
  3823.    EXPECT
  3824.      CASE (TEXTURE_TOKEN)
  3825.        Local_Texture = Default_Texture;
  3826.        Parse_Begin ();
  3827.        Default_Texture = Parse_Texture();
  3828.        Parse_End ();
  3829.        if (Default_Texture->Type != PLAIN_PATTERN)
  3830.          Error("Default texture cannot be material map or tiles.");
  3831.        if (Default_Texture->Next != NULL)
  3832.          Error("Default texture cannot be layered.");
  3833.        Destroy_Textures(Local_Texture);
  3834.      END_CASE
  3835.  
  3836.      CASE (PIGMENT_TOKEN)
  3837.        Local_Pigment = Copy_Pigment((Default_Texture->Pigment));
  3838.        Parse_Begin ();
  3839.        Parse_Pigment (&Local_Pigment);
  3840.        Parse_End ();
  3841.        Destroy_Pigment(Default_Texture->Pigment);
  3842.        Default_Texture->Pigment = Local_Pigment;
  3843.      END_CASE
  3844.  
  3845.      CASE (TNORMAL_TOKEN)
  3846.        Local_Tnormal = Copy_Tnormal((Default_Texture->Tnormal));
  3847.        Parse_Begin ();
  3848.        Parse_Tnormal (&Local_Tnormal);
  3849.        Parse_End ();
  3850.        Destroy_Tnormal(Default_Texture->Tnormal);
  3851.        Default_Texture->Tnormal = Local_Tnormal;
  3852.      END_CASE
  3853.  
  3854.      CASE (FINISH_TOKEN)
  3855.        Local_Finish = Copy_Finish((Default_Texture->Finish));
  3856.        Parse_Finish (&Local_Finish);
  3857.        Destroy_Finish(Default_Texture->Finish);
  3858.        Default_Texture->Finish = Local_Finish;
  3859.      END_CASE
  3860.  
  3861.      CASE (HALO_TOKEN)
  3862.        Local_Halo = Copy_Halo((Default_Texture->Halo));
  3863.        Parse_Halo (&Local_Halo);
  3864.        Destroy_Halo(Default_Texture->Halo);
  3865.        Default_Texture->Halo = Local_Halo;
  3866.      END_CASE
  3867.  
  3868.      CASE (CAMERA_TOKEN)
  3869.        Parse_Camera (&Default_Camera);
  3870.      END_CASE
  3871.  
  3872.      OTHERWISE
  3873.        UNGET
  3874.        EXIT
  3875.      END_CASE
  3876.    END_EXPECT
  3877.  
  3878.    Parse_End();
  3879.  
  3880.    Not_In_Default = TRUE;
  3881. }
  3882.  
  3883.  
  3884.  
  3885. /*****************************************************************************
  3886. *
  3887. * FUNCTION
  3888. *
  3889. * INPUT
  3890. *   
  3891. * OUTPUT
  3892. *   
  3893. * RETURNS
  3894. *   
  3895. * AUTHOR
  3896. *   
  3897. * DESCRIPTION
  3898. *
  3899. * CHANGES
  3900. *
  3901. ******************************************************************************/
  3902.  
  3903. static void Parse_Frame ()
  3904.   {
  3905.    OBJECT *Object;
  3906.    RAINBOW  *Local_Rainbow;
  3907.    FOG  *Local_Fog;
  3908.    SKYSPHERE  *Local_Skysphere;
  3909.    ATMOSPHERE *Local_Atmosphere;
  3910.  
  3911.    EXPECT
  3912.      CASE (RAINBOW_TOKEN)
  3913.        Local_Rainbow = Parse_Rainbow();
  3914.        Local_Rainbow->Next = Frame.Rainbow;
  3915.        Frame.Rainbow = Local_Rainbow;
  3916.      END_CASE
  3917.  
  3918.      CASE (SKYSPHERE_TOKEN)
  3919.        Local_Skysphere = Parse_Skysphere();
  3920.        if (Frame.Skysphere != NULL)
  3921.        {
  3922.          Warn(0.0, "Only one sky-sphere allowed (last one will be used).");
  3923.          Destroy_Skysphere(Frame.Skysphere);
  3924.        }
  3925.        Frame.Skysphere = Local_Skysphere;
  3926.      END_CASE
  3927.  
  3928.      CASE (FOG_TOKEN)
  3929.        Local_Fog = Parse_Fog();
  3930.        Local_Fog->Next = Frame.Fog;
  3931.        Frame.Fog = Local_Fog;
  3932.      END_CASE
  3933.  
  3934.      CASE (ATMOSPHERE_TOKEN)
  3935.        Local_Atmosphere = Parse_Atmosphere();
  3936.        if (Frame.Atmosphere != NULL)
  3937.        {
  3938.          Warn(0.0, "Only one atmosphere allowed (last one will be used).");
  3939.          Destroy_Atmosphere(Frame.Atmosphere);
  3940.        }
  3941.        Frame.Atmosphere = Local_Atmosphere;
  3942.      END_CASE
  3943.  
  3944.      CASE (BACKGROUND_TOKEN)
  3945.        Parse_Begin();
  3946.        Parse_Colour (Frame.Background_Colour);
  3947.        Parse_End();
  3948.      END_CASE
  3949.  
  3950.      CASE (CAMERA_TOKEN)
  3951.        Parse_Camera (&Frame.Camera);
  3952.      END_CASE
  3953.  
  3954.      CASE2 (DECLARE_TOKEN, INCLUDE_TOKEN)
  3955.        UNGET
  3956.        Parse_Directive ();
  3957.        UNGET
  3958.      END_CASE
  3959.  
  3960.      CASE (FLOAT_FUNCT_TOKEN)
  3961.        switch(Token.Function_Id)
  3962.          {
  3963.           case VERSION_TOKEN:
  3964.             UNGET
  3965.             Parse_Directive ();
  3966.             UNGET
  3967.             break;
  3968.             
  3969.           default:
  3970.             UNGET
  3971.             Parse_Error_Str ("object or directive");
  3972.             break;
  3973.          }
  3974.      END_CASE
  3975.  
  3976.      CASE (MAX_TRACE_LEVEL_TOKEN)
  3977.        Global_Setting_Warn();
  3978.        Max_Trace_Level = (int) Parse_Float ();
  3979.      END_CASE
  3980.  
  3981.      CASE (MAX_INTERSECTIONS)
  3982.        Global_Setting_Warn();
  3983.        Max_Intersections = (int)Parse_Float ();
  3984.      END_CASE
  3985.  
  3986.      CASE (DEFAULT_TOKEN)
  3987.        Parse_Default();
  3988.      END_CASE
  3989.  
  3990.      CASE (END_OF_FILE_TOKEN)
  3991.        EXIT
  3992.      END_CASE
  3993.  
  3994.      CASE (GLOBAL_SETTINGS_TOKEN)
  3995.        Parse_Global_Settings();
  3996.      END_CASE
  3997.  
  3998.      OTHERWISE
  3999.        UNGET
  4000.        Object = Parse_Object();
  4001.        if (Object == NULL)
  4002.          Parse_Error_Str ("object or directive");
  4003.        Post_Process (Object, NULL);
  4004.        Link_To_Frame (Object);
  4005.      END_CASE
  4006.    END_EXPECT
  4007.   }
  4008.  
  4009.  
  4010.  
  4011. /*****************************************************************************
  4012. *
  4013. * FUNCTION
  4014. *
  4015. * INPUT
  4016. *   
  4017. * OUTPUT
  4018. *   
  4019. * RETURNS
  4020. *   
  4021. * AUTHOR
  4022. *   
  4023. * DESCRIPTION
  4024. *
  4025. * CHANGES
  4026. *
  4027. *   Mar 1996 : Add line number info to warning message  [AED]
  4028. *
  4029. ******************************************************************************/
  4030.  
  4031. static void Global_Setting_Warn()
  4032. {
  4033.   if (opts.Language_Version >= 3.0)
  4034.   {
  4035.     Warning(0.0, "%s:%d: warning: '%s' should be in 'global_settings{...}' statement.\n",
  4036.             Token.Filename, Token.Token_Line_No+1, Token.Token_String);
  4037.   }
  4038. }
  4039.  
  4040.  
  4041.  
  4042. /*****************************************************************************
  4043. *
  4044. * FUNCTION
  4045. *
  4046. * INPUT
  4047. *   
  4048. * OUTPUT
  4049. *   
  4050. * RETURNS
  4051. *   
  4052. * AUTHOR
  4053. *   
  4054. * DESCRIPTION
  4055. *
  4056. * CHANGES
  4057. *
  4058. ******************************************************************************/
  4059.  
  4060. static void Parse_Global_Settings()
  4061. {
  4062.    Parse_Begin();
  4063.    EXPECT
  4064.      CASE (IRID_WAVELENGTH_TOKEN)
  4065.        Parse_Colour (Frame.Irid_Wavelengths);
  4066.      END_CASE
  4067.  
  4068.      CASE (ASSUMED_GAMMA_TOKEN)
  4069.      {
  4070.        DBL AssumedGamma;
  4071.        AssumedGamma = Parse_Float ();
  4072.  
  4073.        if (fabs(AssumedGamma - opts.DisplayGamma) < 0.1)
  4074.        {
  4075.          opts.GammaFactor = 1.0;
  4076.          opts.Options &= ~GAMMA_CORRECT; /* turn off gamma correction */
  4077.        }
  4078.        else
  4079.        {
  4080.          opts.GammaFactor = AssumedGamma/opts.DisplayGamma;
  4081.          opts.Options |= GAMMA_CORRECT; /* turn on gamma correction */
  4082.        }
  4083.      }
  4084.      END_CASE
  4085.  
  4086.      CASE (MAX_TRACE_LEVEL_TOKEN)
  4087.        Max_Trace_Level = (int) Parse_Float ();
  4088.      END_CASE
  4089.  
  4090.      CASE (ADC_BAILOUT_TOKEN)
  4091.        ADC_Bailout = Parse_Float ();
  4092.      END_CASE
  4093.  
  4094.      CASE (NUMBER_OF_WAVES_TOKEN)
  4095.        Number_Of_Waves = (int) Parse_Float ();
  4096.        if(Number_Of_Waves <=0)
  4097.        {
  4098.          Warn(0.0, "Illegal Value: Number_Of_Waves = 0. Changed to 1.");
  4099.          Number_Of_Waves = 1;
  4100.        }
  4101.      END_CASE
  4102.  
  4103.      CASE (MAX_INTERSECTIONS)
  4104.        Max_Intersections = (int)Parse_Float ();
  4105.      END_CASE
  4106.  
  4107.      CASE (AMBIENT_LIGHT_TOKEN)
  4108.        Parse_Colour (Frame.Ambient_Light);
  4109.      END_CASE
  4110.  
  4111.      CASE (RADIOSITY_TOKEN)
  4112.        Parse_Begin();
  4113.        EXPECT
  4114.          CASE (BRIGHTNESS_TOKEN)
  4115.            if ((opts.Radiosity_Brightness = Parse_Float()) <= 0.0)
  4116.            {
  4117.               Error("Radiosity brightness must be a positive number.");
  4118.            }
  4119.          END_CASE
  4120.  
  4121.          CASE (COUNT_TOKEN)
  4122.            if (( opts.Radiosity_Count = (int)Parse_Float()) <= 0)
  4123.            {
  4124.              Error("Radiosity count must be a positive number.");
  4125.            }
  4126.            if ( opts.Radiosity_Count > 1600)
  4127.            {
  4128.              Error("Radiosity count can not be more than 1600.");
  4129.              opts.Radiosity_Count = 1600;
  4130.            }
  4131.          END_CASE
  4132.  
  4133.          CASE (DISTANCE_MAXIMUM_TOKEN)
  4134.            if (( opts.Radiosity_Dist_Max = Parse_Float()) < 0.0)
  4135.            {
  4136.              Error("Radiosity distance maximum must be a positive number.");
  4137.            }
  4138.          END_CASE
  4139.  
  4140.          CASE (ERROR_BOUND_TOKEN)
  4141.            if (( opts.Radiosity_Error_Bound = Parse_Float()) <= 0.0)
  4142.            {
  4143.              Error("Radiosity error bound must be a positive number.");
  4144.            }
  4145.          END_CASE
  4146.  
  4147.          CASE (GRAY_THRESHOLD_TOKEN)
  4148.            opts.Radiosity_Gray = Parse_Float();
  4149.            if (( opts.Radiosity_Gray < 0.0) || ( opts.Radiosity_Gray > 1.0))
  4150.            {
  4151.               Error("Radiosity gray threshold must be from 0.0 to 1.0.");
  4152.            }
  4153.          END_CASE
  4154.  
  4155.          CASE (LOW_ERROR_FACTOR_TOKEN)
  4156.            if (( opts.Radiosity_Low_Error_Factor = Parse_Float()) <= 0.0)
  4157.            {
  4158.              Error("Radiosity low error factor must be a positive number.");
  4159.            }
  4160.          END_CASE
  4161.  
  4162.          CASE (MINIMUM_REUSE_TOKEN)
  4163.            if (( opts.Radiosity_Min_Reuse = Parse_Float()) < 0.0)
  4164.            {
  4165.               Error("Radiosity min reuse can not be a negative number.");
  4166.            }
  4167.          END_CASE
  4168.  
  4169.          CASE (NEAREST_COUNT_TOKEN)
  4170.            opts.Radiosity_Nearest_Count = (int)Parse_Float();
  4171.            if (( opts.Radiosity_Nearest_Count < 1) ||
  4172.                ( opts.Radiosity_Nearest_Count > MAX_NEAREST_COUNT))
  4173.            {
  4174.               Error("Radiosity nearest count must be a value from 1 to %ld.", (long)MAX_NEAREST_COUNT);
  4175.            }
  4176.          END_CASE
  4177.  
  4178.          CASE (RECURSION_LIMIT_TOKEN)
  4179.            if (( opts.Radiosity_Recursion_Limit = (int)Parse_Float()) <= 0)
  4180.            {
  4181.               Error("Radiosity recursion limit must be a positive number.");
  4182.            }
  4183.          END_CASE
  4184.  
  4185.          OTHERWISE
  4186.            UNGET
  4187.            EXIT
  4188.          END_CASE
  4189.        END_EXPECT
  4190.        Parse_End();
  4191.      END_CASE
  4192.  
  4193.      CASE (HF_GRAY_16_TOKEN)
  4194.        if (Allow_Float(1.0)>EPSILON)     
  4195.        {
  4196.          opts.Options |= HF_GRAY_16;
  4197.          opts.PaletteOption = GREY;        /* Force gray scale preview */
  4198.          Output_File_Handle->file_type = HF_FTYPE;
  4199.        }
  4200.      END_CASE
  4201.  
  4202.      OTHERWISE
  4203.        UNGET
  4204.        EXIT
  4205.      END_CASE
  4206.    END_EXPECT
  4207.    Parse_End();
  4208. }
  4209.  
  4210.  
  4211.  
  4212. /*****************************************************************************
  4213. *
  4214. * FUNCTION
  4215. *
  4216. * INPUT
  4217. *   
  4218. * OUTPUT
  4219. *   
  4220. * RETURNS
  4221. *   
  4222. * AUTHOR
  4223. *   
  4224. * DESCRIPTION
  4225. *
  4226. * CHANGES
  4227. *
  4228. ******************************************************************************/
  4229.  
  4230. void Destroy_Frame()
  4231. {
  4232.     FOG *Fog, *Next_Fog;
  4233.     RAINBOW *Rainbow, *Next_Rainbow;
  4234.  
  4235.     Destroy_Camera (Frame.Camera); Frame.Camera=NULL;
  4236.  
  4237.     /* Destroy fogs. [DB 12/94] */
  4238.  
  4239.     for (Fog = Frame.Fog; Fog != NULL;)
  4240.     {
  4241.       Next_Fog = Fog->Next;
  4242.  
  4243.       Destroy_Fog(Fog);
  4244.  
  4245.       Fog = Next_Fog;
  4246.     }
  4247.     
  4248.     Frame.Fog = NULL;
  4249.  
  4250.     /* Destroy rainbows. [DB 12/94] */
  4251.  
  4252.     for (Rainbow = Frame.Rainbow; Rainbow != NULL;)
  4253.     {
  4254.       Next_Rainbow = Rainbow->Next;
  4255.  
  4256.       Destroy_Rainbow(Rainbow);
  4257.  
  4258.       Rainbow = Next_Rainbow;
  4259.     }
  4260.  
  4261.     Frame.Rainbow = NULL;
  4262.  
  4263.     /* Destroy skysphere. [DB 12/94] */
  4264.  
  4265.     Destroy_Skysphere(Frame.Skysphere);
  4266.  
  4267.     Frame.Skysphere = NULL;
  4268.  
  4269.     /* Destroy atmosphere. [DB 1/95] */
  4270.  
  4271.     Destroy_Atmosphere(Frame.Atmosphere);
  4272.  
  4273.     Frame.Atmosphere = NULL;
  4274.  
  4275.     if (Frame.Objects != NULL) {
  4276.        Destroy_Object (Frame.Objects);
  4277.        Frame.Objects = NULL;
  4278.        Frame.Light_Sources = NULL;
  4279.     }
  4280. }
  4281.  
  4282.  
  4283.  
  4284.  
  4285. /*****************************************************************************
  4286. *
  4287. * FUNCTION
  4288. *
  4289. * INPUT
  4290. *
  4291. * OUTPUT
  4292. *
  4293. * RETURNS
  4294. *
  4295. * AUTHOR
  4296. *
  4297. * DESCRIPTION
  4298. *
  4299. * CHANGES
  4300. *
  4301. ******************************************************************************/
  4302.  
  4303. static void Parse_Camera (Camera_Ptr)
  4304. CAMERA **Camera_Ptr;
  4305. {
  4306.    int i;
  4307.    DBL Direction_Length = 1.0, Up_Length, Right_Length, Handedness;
  4308.    DBL k1, k2, k3;
  4309.    VECTOR Local_Vector;
  4310.    MATRIX Local_Matrix;
  4311.    TRANSFORM Local_Trans;
  4312.    CAMERA *New;
  4313.  
  4314.    Parse_Begin ();
  4315.  
  4316.    EXPECT
  4317.      CASE (CAMERA_ID_TOKEN)
  4318.        Destroy_Camera(*Camera_Ptr);
  4319.        *Camera_Ptr = Copy_Camera ((CAMERA *) Token.Constant_Data);
  4320.        EXIT
  4321.      END_CASE
  4322.  
  4323.      OTHERWISE
  4324.        UNGET
  4325.        EXIT
  4326.      END_CASE
  4327.    END_EXPECT
  4328.  
  4329.    New = *Camera_Ptr;
  4330.  
  4331.    EXPECT
  4332.      /* Get camera type. [DB 7/94] */
  4333.  
  4334.      CASE (PERSPECTIVE_TOKEN)
  4335.        New->Type = PERSPECTIVE_CAMERA;
  4336.      END_CASE
  4337.  
  4338.      CASE (ORTHOGRAPHIC_TOKEN)
  4339.        New->Type = ORTHOGRAPHIC_CAMERA;
  4340.        /* 
  4341.         * Resize right and up vector to get the same image 
  4342.         * area as we get with the perspective camera. 
  4343.         */
  4344.        VSub(Local_Vector, New->Look_At, New->Location);
  4345.        VLength(k1, Local_Vector);
  4346.        VLength(k2, New->Direction);
  4347.        if ((k1 > EPSILON) && (k2 > EPSILON))
  4348.        {
  4349.          VScaleEq(New->Right, k1 / k2);
  4350.          VScaleEq(New->Up, k1 / k2);
  4351.        }
  4352.      END_CASE
  4353.  
  4354.      CASE (FISHEYE_TOKEN)
  4355.        New->Type = FISHEYE_CAMERA;
  4356.      END_CASE
  4357.  
  4358.      CASE (ULTRA_WIDE_ANGLE_TOKEN)
  4359.        New->Type = ULTRA_WIDE_ANGLE_CAMERA;
  4360.      END_CASE
  4361.  
  4362.      CASE (OMNIMAX_TOKEN)
  4363.        New->Type = OMNIMAX_CAMERA;
  4364.      END_CASE
  4365.  
  4366.      CASE (PANORAMIC_TOKEN)
  4367.        New->Type = PANORAMIC_CAMERA;
  4368.      END_CASE
  4369.  
  4370.      CASE (CYLINDER_TOKEN)
  4371.        i = (int)Parse_Float();
  4372.        switch (i)
  4373.        {
  4374.          case 1: New->Type = CYL_1_CAMERA; break;
  4375.          case 2: New->Type = CYL_2_CAMERA; break;
  4376.          case 3: New->Type = CYL_3_CAMERA; break;
  4377.          case 4: New->Type = CYL_4_CAMERA; break;
  4378.        }       
  4379.      END_CASE
  4380.  
  4381.      CASE (TEST_CAMERA_1_TOKEN)
  4382.        New->Type = TEST_CAMERA_1;
  4383.      END_CASE
  4384.  
  4385.      CASE (TEST_CAMERA_2_TOKEN)
  4386.        New->Type = TEST_CAMERA_2;
  4387.      END_CASE
  4388.  
  4389.      CASE (TEST_CAMERA_3_TOKEN)
  4390.        New->Type = TEST_CAMERA_3;
  4391.      END_CASE
  4392.  
  4393.      CASE (TEST_CAMERA_4_TOKEN)
  4394.        New->Type = TEST_CAMERA_4;
  4395.      END_CASE
  4396.  
  4397.      /* Read viewing angle. Scale direction vector if necessary. [DB 7/94] */
  4398.  
  4399.      CASE (ANGLE_TOKEN)
  4400.        New->Angle = Parse_Float();
  4401.  
  4402.        if (New->Angle < 0.0)
  4403.        {
  4404.          Error("Negative viewing angle.");
  4405.        }
  4406.  
  4407.        if (New->Type == PERSPECTIVE_CAMERA)
  4408.        {
  4409.          if (New->Angle >= 180.0)
  4410.          {
  4411.            Error("Viewing angle has to be smaller than 180 degrees.");
  4412.          }
  4413.  
  4414.          VNormalize(New->Direction, New->Direction);
  4415.  
  4416.          VLength (Right_Length, New->Right);
  4417.  
  4418.          Direction_Length = Right_Length / tan(New->Angle * M_PI / 360.0)/2.0;
  4419.  
  4420.          VScaleEq(New->Direction, Direction_Length);
  4421.        }
  4422.      END_CASE
  4423.  
  4424.  
  4425.      /* Read primary ray pertubation. [DB 7/94] */
  4426.  
  4427.      CASE (TNORMAL_TOKEN)
  4428.        Parse_Begin ();
  4429.        Parse_Tnormal(&(New->Tnormal));
  4430.        Parse_End ();
  4431.      END_CASE
  4432.  
  4433.      CASE (LOCATION_TOKEN)
  4434.        Parse_Vector(New->Location);
  4435.      END_CASE
  4436.  
  4437.      CASE (DIRECTION_TOKEN)
  4438.        Parse_Vector(New->Direction);
  4439.      END_CASE
  4440.  
  4441.      CASE (UP_TOKEN)
  4442.        Parse_Vector(New->Up);
  4443.      END_CASE
  4444.  
  4445.      CASE (RIGHT_TOKEN)
  4446.        Parse_Vector(New->Right);
  4447.      END_CASE
  4448.  
  4449.      CASE (SKY_TOKEN)
  4450.        Parse_Vector(New->Sky);
  4451.      END_CASE
  4452.  
  4453.      CASE (LOOK_AT_TOKEN)
  4454.        VLength (Direction_Length, New->Direction);
  4455.        VLength (Up_Length,        New->Up);
  4456.        VLength (Right_Length,     New->Right);
  4457.        VCross  (Local_Vector,     New->Up,        New->Direction);
  4458.        VDot    (Handedness,       Local_Vector,   New->Right);
  4459.  
  4460.        Parse_Vector (New->Direction);
  4461.        Assign_Vector(New->Look_At, New->Direction);
  4462.  
  4463.        VSub          (New->Direction, New->Direction, New->Location);
  4464.  
  4465.        /* Check for zero length direction vector. */
  4466.  
  4467.        if (VSumSqr(New->Direction) < EPSILON)
  4468.        {
  4469.          Error("Camera location and look_at point must be different.\n");
  4470.        }
  4471.        
  4472.        VNormalize    (New->Direction, New->Direction);
  4473.  
  4474.        /* Save Right vector */
  4475.  
  4476.        Assign_Vector (Local_Vector, New->Right);
  4477.  
  4478.        VCross        (New->Right, New->Sky, New->Direction);
  4479.  
  4480.        /* Avoid DOMAIN error (from Terry Kanakis) */
  4481.  
  4482.        if((fabs(New->Right[X]) < EPSILON) &&
  4483.           (fabs(New->Right[Y]) < EPSILON) &&
  4484.           (fabs(New->Right[Z]) < EPSILON))
  4485.        {
  4486.          /* Restore Right vector*/
  4487.  
  4488.          Assign_Vector (New->Right, Local_Vector);
  4489.        }
  4490.  
  4491.        VNormalize (New->Right,     New->Right);
  4492.        VCross     (New->Up,        New->Direction, New->Right);
  4493.        VScale     (New->Direction, New->Direction, Direction_Length);
  4494.  
  4495.        if (Handedness > 0.0)
  4496.          VScaleEq (New->Right, Right_Length)
  4497.        else
  4498.          VScaleEq (New->Right, -Right_Length);
  4499.  
  4500.        VScaleEq(New->Up, Up_Length);
  4501.      END_CASE
  4502.  
  4503.      CASE (TRANSLATE_TOKEN)
  4504.        Parse_Vector (Local_Vector);
  4505.        Translate_Camera (New, Local_Vector);
  4506.      END_CASE
  4507.  
  4508.      CASE (ROTATE_TOKEN)
  4509.        Parse_Vector (Local_Vector);
  4510.        Rotate_Camera (New, Local_Vector);
  4511.      END_CASE
  4512.  
  4513.      CASE (SCALE_TOKEN)
  4514.        Parse_Scale_Vector (Local_Vector);
  4515.        Scale_Camera (New, Local_Vector);
  4516.      END_CASE
  4517.  
  4518.      CASE (TRANSFORM_TOKEN)
  4519.        GET(TRANSFORM_ID_TOKEN)
  4520.        Transform_Camera (New, (TRANSFORM *)Token.Constant_Data);
  4521.      END_CASE
  4522.  
  4523.      CASE (MATRIX_TOKEN)
  4524.        Parse_Matrix (Local_Matrix);
  4525.        Compute_Matrix_Transform(&Local_Trans, Local_Matrix);
  4526.        Transform_Camera (New, &Local_Trans);
  4527.      END_CASE
  4528.  
  4529.      /* Parse focal blur stuff. */
  4530.  
  4531.      CASE (BLUR_SAMPLES_TOKEN)
  4532.         New->Blur_Samples = Parse_Float();
  4533.         if (New->Blur_Samples <= 0)
  4534.         {
  4535.           Error("Illegal number of focal blur samples.\n");
  4536.         }
  4537.      END_CASE
  4538.  
  4539.      CASE (CONFIDENCE_TOKEN)
  4540.         k1 = Parse_Float();
  4541.         if ((k1 > 0.0) && (k1 < 1.0))
  4542.         {
  4543.           New->Confidence = k1;
  4544.         }
  4545.         else
  4546.         {
  4547.           Warn(0.0, "Illegal confidence value. Default is used.");
  4548.         }
  4549.      END_CASE
  4550.  
  4551.      CASE (VARIANCE_TOKEN)
  4552.         k1 = Parse_Float();
  4553.         if ((k1 >= 0.0) && (k1 <= 1.0))
  4554.         {
  4555.           New->Variance = k1;
  4556.         }
  4557.         else
  4558.         {
  4559.           Warn(0.0, "Illegal variance value. Default is used.");
  4560.         }
  4561.      END_CASE
  4562.  
  4563.      CASE (APERTURE_TOKEN)
  4564.         New->Aperture = Parse_Float();
  4565.      END_CASE
  4566.  
  4567.      CASE (FOCAL_POINT_TOKEN)
  4568.         Parse_Vector(Local_Vector);
  4569.         VSubEq(Local_Vector, New->Location);
  4570.         VLength (New->Focal_Distance, Local_Vector);
  4571.      END_CASE
  4572.  
  4573.      OTHERWISE
  4574.        UNGET
  4575.        EXIT
  4576.      END_CASE
  4577.    END_EXPECT
  4578.    Parse_End ();
  4579.  
  4580.    /* Make sure the focal distance hasn't been explicitly given */
  4581.    if ( New->Focal_Distance < 0.0 )
  4582.       New->Focal_Distance = Direction_Length;
  4583.    if ( New->Focal_Distance == 0.0 )
  4584.       New->Focal_Distance = 1.0;
  4585.  
  4586.    /* Print a warning message if vectors are not perpendicular. [DB 10/94] */
  4587.  
  4588.    VDot(k1, New->Right, New->Up);
  4589.    VDot(k2, New->Right, New->Direction);
  4590.    VDot(k3, New->Up, New->Direction);
  4591.  
  4592.    if ((fabs(k1) > EPSILON) || (fabs(k2) > EPSILON) || (fabs(k3) > EPSILON))
  4593.    {
  4594.      Warn(0.0, "Camera vectors are not perpendicular. "
  4595.                "Making look_at the last statement may help.");
  4596.    }
  4597. }
  4598.  
  4599.  
  4600.  
  4601. /*****************************************************************************
  4602. *
  4603. * FUNCTION
  4604. *
  4605. * INPUT
  4606. *
  4607. * OUTPUT
  4608. *
  4609. * RETURNS
  4610. *
  4611. * AUTHOR
  4612. *
  4613. * DESCRIPTION
  4614. *
  4615. * CHANGES
  4616. *
  4617. ******************************************************************************/
  4618.  
  4619. void Parse_Matrix(Matrix)
  4620. MATRIX Matrix;
  4621. {
  4622.   int i, j;
  4623.  
  4624.   EXPECT
  4625.     CASE (LEFT_ANGLE_TOKEN)
  4626.       Matrix[0][0] = Parse_Float();
  4627.       for (i = 0; i < 4; i++)
  4628.       {
  4629.         for (j = !i ? 1 : 0; j < 3; j++)
  4630.         {
  4631.           Parse_Comma();
  4632.  
  4633.           Matrix[i][j] = Parse_Float();
  4634.         }
  4635.  
  4636.         Matrix[i][3] = (i != 3 ? 0.0 : 1.0);
  4637.       }
  4638.       GET (RIGHT_ANGLE_TOKEN);
  4639.  
  4640.       /* Check to see that we aren't scaling any dimension by zero */
  4641.       for (i = 0; i < 3; i++)
  4642.       {
  4643.         if (fabs(Matrix[0][i]) < EPSILON && fabs(Matrix[1][i]) < EPSILON &&
  4644.             fabs(Matrix[2][i]) < EPSILON)
  4645.         {
  4646.           Warn(0.0,"Illegal matrix column: Scale by 0.0. Changed to 1.0.");
  4647.           Matrix[i][i] = 1.0;
  4648.         }
  4649.       }
  4650.       EXIT
  4651.     END_CASE
  4652.  
  4653.     OTHERWISE
  4654.       Parse_Error (LEFT_ANGLE_TOKEN);
  4655.     END_CASE
  4656.   END_EXPECT
  4657. }
  4658.  
  4659.  
  4660.  
  4661. /*****************************************************************************
  4662. *
  4663. * FUNCTION
  4664. *
  4665. * INPUT
  4666. *
  4667. * OUTPUT
  4668. *
  4669. * RETURNS
  4670. *
  4671. * AUTHOR
  4672. *
  4673. * DESCRIPTION
  4674. *
  4675. * CHANGES
  4676. *
  4677. ******************************************************************************/
  4678.  
  4679. static
  4680. TRANSFORM *Parse_Transform ()
  4681.   {
  4682.    MATRIX Local_Matrix;
  4683.    TRANSFORM *New, Local_Trans;
  4684.    VECTOR Local_Vector;
  4685.  
  4686.    Parse_Begin ();
  4687.    New = Create_Transform ();
  4688.  
  4689.    EXPECT
  4690.      CASE(TRANSFORM_ID_TOKEN)
  4691.        Compose_Transforms (New, (TRANSFORM *)Token.Constant_Data);
  4692.        EXIT
  4693.      END_CASE
  4694.  
  4695.      CASE (TRANSLATE_TOKEN)
  4696.        Parse_Vector (Local_Vector);
  4697.        Compute_Translation_Transform(&Local_Trans, Local_Vector);
  4698.        Compose_Transforms (New, &Local_Trans);
  4699.      END_CASE
  4700.  
  4701.      CASE (ROTATE_TOKEN)
  4702.        Parse_Vector (Local_Vector);
  4703.        Compute_Rotation_Transform(&Local_Trans, Local_Vector);
  4704.        Compose_Transforms (New, &Local_Trans);
  4705.      END_CASE
  4706.  
  4707.      CASE (SCALE_TOKEN)
  4708.        Parse_Scale_Vector (Local_Vector);
  4709.        Compute_Scaling_Transform(&Local_Trans, Local_Vector);
  4710.        Compose_Transforms (New, &Local_Trans);
  4711.      END_CASE
  4712.  
  4713.      CASE (MATRIX_TOKEN)
  4714.        Parse_Matrix(Local_Matrix);
  4715.        Compute_Matrix_Transform(&Local_Trans, Local_Matrix);
  4716.        Compose_Transforms (New, &Local_Trans);
  4717.      END_CASE
  4718.  
  4719.      OTHERWISE
  4720.        UNGET
  4721.        EXIT
  4722.      END_CASE
  4723.    END_EXPECT
  4724.  
  4725.    Parse_End ();
  4726.    return (New);
  4727.   }
  4728.  
  4729.  
  4730.  
  4731. /*****************************************************************************
  4732. *
  4733. * FUNCTION
  4734. *
  4735. * INPUT
  4736. *   
  4737. * OUTPUT
  4738. *   
  4739. * RETURNS
  4740. *   
  4741. * AUTHOR
  4742. *   
  4743. * DESCRIPTION
  4744. *
  4745. * CHANGES
  4746. *
  4747. ******************************************************************************/
  4748.  
  4749. void Parse_Declare ()
  4750.   {
  4751.   VECTOR Local_Vector;
  4752.   COLOUR *Local_Colour;
  4753.   PIGMENT *Local_Pigment;
  4754.   TNORMAL *Local_Tnormal;
  4755.   FINISH *Local_Finish;
  4756.   HALO *Local_Halo = NULL;
  4757.   TEXTURE *Local_Texture, *Temp_Texture;
  4758.   TRANSFORM *Local_Trans;
  4759.   OBJECT *Local_Object;
  4760.   CAMERA *Local_Camera;
  4761.   char *Temp_Data;
  4762.   int Previous;
  4763.  
  4764.   struct Constant_Struct *Constant_Ptr = NULL;
  4765.  
  4766.   EXPECT
  4767.     CASE (IDENTIFIER_TOKEN)
  4768.       if (++Number_Of_Constants >= Max_Constants)
  4769.       {
  4770.         if (Max_Constants >= INT_MAX/2)
  4771.         {
  4772.           Error("Too many constants declared.\n");
  4773.         }
  4774.  
  4775.         Max_Constants *= 2;
  4776.  
  4777.         Constants = (struct Constant_Struct *)POV_REALLOC(Constants, (Max_Constants+1) * sizeof(struct Constant_Struct), "constants table");
  4778.       }
  4779.  
  4780.       Constant_Ptr = &(Constants[Number_Of_Constants]);
  4781.       Constant_Ptr->Constant_Type = IDENTIFIER_TOKEN;
  4782.       EXIT
  4783.     END_CASE
  4784.  
  4785.     CASE4 (TNORMAL_ID_TOKEN, FINISH_ID_TOKEN, TEXTURE_ID_TOKEN, OBJECT_ID_TOKEN)
  4786.     CASE4 (COLOUR_MAP_ID_TOKEN, TRANSFORM_ID_TOKEN, CAMERA_ID_TOKEN, PIGMENT_ID_TOKEN)
  4787.     CASE4 (SLOPE_MAP_ID_TOKEN,NORMAL_MAP_ID_TOKEN,TEXTURE_MAP_ID_TOKEN,COLOUR_ID_TOKEN)
  4788.     CASE3 (PIGMENT_MAP_ID_TOKEN, HALO_ID_TOKEN,STRING_ID_TOKEN)
  4789.       Constant_Ptr = &(Constants[Token.Constant_Index]);
  4790.       EXIT
  4791.     END_CASE
  4792.  
  4793.     CASE2 (VECTOR_FUNCT_TOKEN, FLOAT_FUNCT_TOKEN)
  4794.       switch(Token.Function_Id)
  4795.         {
  4796.          case VECTOR_ID_TOKEN:
  4797.          case FLOAT_ID_TOKEN:
  4798.            Constant_Ptr = &(Constants[Token.Constant_Index]);
  4799.            break;
  4800.  
  4801.          default:
  4802.            Parse_Error(IDENTIFIER_TOKEN);
  4803.            break;
  4804.         }
  4805.       EXIT
  4806.     END_CASE
  4807.  
  4808.     OTHERWISE
  4809.       Parse_Error(IDENTIFIER_TOKEN);
  4810.     END_CASE
  4811.   END_EXPECT
  4812.  
  4813.   Previous = Token.Token_Id;
  4814.  
  4815.   GET (EQUALS_TOKEN);
  4816.  
  4817.   EXPECT
  4818.     CASE_COLOUR
  4819.       Local_Colour = Create_Colour();
  4820.       Ok_To_Declare = FALSE;
  4821.       Parse_Colour (*Local_Colour);
  4822.       Ok_To_Declare = TRUE;
  4823.       if (Test_Redefine(Previous,COLOUR_ID_TOKEN))
  4824.         Destroy_Colour((COLOUR *)Constant_Ptr->Constant_Data);
  4825.       Constant_Ptr->Constant_Data = (char *) Local_Colour;
  4826.       Constant_Ptr->Constant_Type = COLOUR_ID_TOKEN;
  4827.       EXIT
  4828.     END_CASE
  4829.  
  4830.     CASE_VECTOR
  4831.       Ok_To_Declare = FALSE;
  4832.       Have_Vector = FALSE;
  4833.       Parse_Vector_Float (Local_Vector);
  4834.       if (Have_Vector)
  4835.         {
  4836.          if (Test_Redefine(Previous,VECTOR_FUNCT_TOKEN))
  4837.            Destroy_Vector((VECTOR *)Constant_Ptr->Constant_Data);
  4838.          Constant_Ptr->Constant_Type = VECTOR_ID_TOKEN;
  4839.          Constant_Ptr->Constant_Data = (char *) Create_Vector();
  4840.          Assign_Vector(Constant_Ptr->Constant_Data,Local_Vector);
  4841.         }
  4842.       else
  4843.         {
  4844.          if (Test_Redefine(Previous,FLOAT_FUNCT_TOKEN))
  4845.            Destroy_Float((DBL *)Constant_Ptr->Constant_Data);
  4846.          Constant_Ptr->Constant_Type = FLOAT_ID_TOKEN;
  4847.                         Constant_Ptr->Constant_Data = (char *) Create_Float();
  4848.          *((DBL *) Constant_Ptr->Constant_Data) = Local_Vector[X];
  4849.         }
  4850.       Ok_To_Declare = TRUE;
  4851.       EXIT
  4852.     END_CASE
  4853.  
  4854.     CASE (PIGMENT_TOKEN)
  4855.       Local_Pigment = Copy_Pigment((Default_Texture->Pigment));
  4856.       Parse_Begin ();
  4857.       Parse_Pigment (&Local_Pigment);
  4858.       Parse_End ();
  4859.       if (Test_Redefine(Previous,PIGMENT_ID_TOKEN))
  4860.         Destroy_Pigment((PIGMENT *)Constant_Ptr->Constant_Data);
  4861.       Constant_Ptr->Constant_Type = PIGMENT_ID_TOKEN;
  4862.       Constant_Ptr->Constant_Data = (char *)Local_Pigment;
  4863.       EXIT
  4864.     END_CASE
  4865.  
  4866.     CASE (TNORMAL_TOKEN)
  4867.       Local_Tnormal = Copy_Tnormal((Default_Texture->Tnormal));
  4868.       Parse_Begin ();
  4869.       Parse_Tnormal (&Local_Tnormal);
  4870.       Parse_End ();
  4871.       if (Test_Redefine(Previous,TNORMAL_ID_TOKEN))
  4872.         Destroy_Tnormal((TNORMAL *)Constant_Ptr->Constant_Data);
  4873.       Constant_Ptr->Constant_Type = TNORMAL_ID_TOKEN;
  4874.       Constant_Ptr->Constant_Data = (char *) Local_Tnormal;
  4875.       EXIT
  4876.     END_CASE
  4877.  
  4878.     CASE (FINISH_TOKEN)
  4879.       Local_Finish = Copy_Finish((Default_Texture->Finish));
  4880.       Parse_Finish (&Local_Finish);
  4881.       if (Test_Redefine(Previous,FINISH_ID_TOKEN))
  4882.         Destroy_Finish((FINISH *)Constant_Ptr->Constant_Data);
  4883.       Constant_Ptr->Constant_Type = FINISH_ID_TOKEN;
  4884.       Constant_Ptr->Constant_Data = (char *) Local_Finish;
  4885.       EXIT
  4886.     END_CASE
  4887.  
  4888.     CASE (HALO_TOKEN)
  4889.       Local_Halo = Copy_Halo((Default_Texture->Halo));
  4890.       Parse_Halo (&Local_Halo);
  4891.       if (Test_Redefine(Previous,HALO_ID_TOKEN))
  4892.         Destroy_Halo((HALO *)Constant_Ptr->Constant_Data);
  4893.       Constant_Ptr->Constant_Type = HALO_ID_TOKEN;
  4894.       Constant_Ptr->Constant_Data = (char *) Local_Halo;
  4895.       EXIT
  4896.     END_CASE
  4897.  
  4898.     CASE (CAMERA_TOKEN)
  4899.       Local_Camera = Copy_Camera(Default_Camera);
  4900.       Parse_Camera (&Local_Camera);
  4901.       if (Test_Redefine(Previous,CAMERA_ID_TOKEN))
  4902.         Destroy_Camera((CAMERA *)Constant_Ptr->Constant_Data);
  4903.       Constant_Ptr->Constant_Type = CAMERA_ID_TOKEN;
  4904.       Constant_Ptr->Constant_Data = (char *) Local_Camera;
  4905.       EXIT
  4906.     END_CASE
  4907.  
  4908.     CASE (TEXTURE_TOKEN)
  4909.       Parse_Begin ();
  4910.       Local_Texture = Parse_Texture ();
  4911.       Parse_End ();
  4912.       Temp_Texture=NULL;
  4913.       Link_Textures(&Temp_Texture, Local_Texture);
  4914.       Ok_To_Declare = FALSE;
  4915.       EXPECT
  4916.         CASE (TEXTURE_TOKEN)
  4917.           Parse_Begin ();
  4918.           Local_Texture = Parse_Texture ();
  4919.           Parse_End ();
  4920.           Link_Textures(&Temp_Texture, Local_Texture);
  4921.         END_CASE
  4922.  
  4923.         OTHERWISE
  4924.           UNGET
  4925.           EXIT
  4926.         END_CASE
  4927.       END_EXPECT
  4928.  
  4929.       if (Test_Redefine(Previous,TEXTURE_ID_TOKEN))
  4930.       {
  4931.         Destroy_Textures((TEXTURE *)Constant_Ptr->Constant_Data);
  4932.       }
  4933.       Constant_Ptr->Constant_Type = TEXTURE_ID_TOKEN;
  4934.       Constant_Ptr->Constant_Data = (char *)Temp_Texture;
  4935.       Ok_To_Declare = TRUE;
  4936.       EXIT
  4937.     END_CASE
  4938.  
  4939.     CASE (COLOUR_MAP_TOKEN)
  4940.       Ok_To_Declare = FALSE;
  4941.       Temp_Data=(char *) Parse_Colour_Map ();
  4942.       if (Test_Redefine(Previous,COLOUR_MAP_ID_TOKEN))
  4943.         Destroy_Blend_Map((BLEND_MAP *)Constant_Ptr->Constant_Data);
  4944.       Constant_Ptr->Constant_Type = COLOUR_MAP_ID_TOKEN;
  4945.       Constant_Ptr->Constant_Data = Temp_Data;
  4946.       EXIT
  4947.     END_CASE
  4948.  
  4949.     CASE (PIGMENT_MAP_TOKEN)
  4950.       Temp_Data = (char *) Parse_Blend_Map (PIGMENT_TYPE,NO_PATTERN);
  4951.       if (Test_Redefine(Previous,PIGMENT_MAP_ID_TOKEN))
  4952.         Destroy_Blend_Map((BLEND_MAP *)Constant_Ptr->Constant_Data);
  4953.       Constant_Ptr->Constant_Type = PIGMENT_MAP_ID_TOKEN;
  4954.       Constant_Ptr->Constant_Data = Temp_Data;
  4955.       EXIT
  4956.     END_CASE
  4957.  
  4958.     CASE (SLOPE_MAP_TOKEN)
  4959.       Temp_Data = (char *) Parse_Blend_Map (SLOPE_TYPE,NO_PATTERN);
  4960.       Constant_Ptr->Constant_Type = SLOPE_MAP_ID_TOKEN;
  4961.       if (Test_Redefine(Previous,SLOPE_MAP_ID_TOKEN))
  4962.         Destroy_Blend_Map((BLEND_MAP *)Constant_Ptr->Constant_Data);
  4963.       Constant_Ptr->Constant_Data = Temp_Data;
  4964.       EXIT
  4965.     END_CASE
  4966.  
  4967.     CASE (TEXTURE_MAP_TOKEN)
  4968.       Temp_Data = (char *) Parse_Blend_Map (TEXTURE_TYPE,NO_PATTERN);
  4969.       Constant_Ptr->Constant_Type = TEXTURE_MAP_ID_TOKEN;
  4970.       if (Test_Redefine(Previous,TEXTURE_MAP_ID_TOKEN))
  4971.         Destroy_Blend_Map((BLEND_MAP *)Constant_Ptr->Constant_Data);
  4972.       Constant_Ptr->Constant_Data = Temp_Data;
  4973.       EXIT
  4974.     END_CASE
  4975.  
  4976.     CASE (NORMAL_MAP_TOKEN)
  4977.       Temp_Data= (char *) Parse_Blend_Map (NORMAL_TYPE,NO_PATTERN);
  4978.       Constant_Ptr->Constant_Type = NORMAL_MAP_ID_TOKEN;
  4979.       if (Test_Redefine(Previous,NORMAL_MAP_ID_TOKEN))
  4980.         Destroy_Blend_Map((BLEND_MAP *)Constant_Ptr->Constant_Data);
  4981.       Constant_Ptr->Constant_Data = Temp_Data;
  4982.       EXIT
  4983.     END_CASE
  4984.  
  4985.     CASE (RAINBOW_TOKEN)
  4986.       Temp_Data= (char *) Parse_Rainbow();
  4987.       Constant_Ptr->Constant_Type = RAINBOW_ID_TOKEN;
  4988.       if (Test_Redefine(Previous,RAINBOW_ID_TOKEN))
  4989.         Destroy_Rainbow((RAINBOW *)Constant_Ptr->Constant_Data);
  4990.       Constant_Ptr->Constant_Data = Temp_Data;
  4991.       EXIT
  4992.     END_CASE
  4993.  
  4994.     CASE (FOG_TOKEN)
  4995.       Temp_Data= (char *) Parse_Fog();
  4996.       if (Test_Redefine(Previous,FOG_ID_TOKEN))
  4997.         Destroy_Fog((FOG *)Constant_Ptr->Constant_Data);
  4998.       Constant_Ptr->Constant_Data = Temp_Data;
  4999.       Constant_Ptr->Constant_Type = FOG_ID_TOKEN;
  5000.       EXIT
  5001.     END_CASE
  5002.  
  5003.     CASE (ATMOSPHERE_TOKEN)
  5004.       Temp_Data= (char *) Parse_Atmosphere();
  5005.       if (Test_Redefine(Previous,ATMOSPHERE_ID_TOKEN))
  5006.         Destroy_Atmosphere((ATMOSPHERE *)Constant_Ptr->Constant_Data);
  5007.       Constant_Ptr->Constant_Data = Temp_Data;
  5008.       Constant_Ptr->Constant_Type = ATMOSPHERE_ID_TOKEN;
  5009.       EXIT
  5010.     END_CASE
  5011.  
  5012.     CASE (SKYSPHERE_TOKEN)
  5013.       Temp_Data= (char *) Parse_Skysphere();
  5014.       if (Test_Redefine(Previous,SKYSPHERE_ID_TOKEN))
  5015.         Destroy_Skysphere((SKYSPHERE *)Constant_Ptr->Constant_Data);
  5016.       Constant_Ptr->Constant_Data = Temp_Data;
  5017.       Constant_Ptr->Constant_Type = SKYSPHERE_ID_TOKEN;
  5018.       EXIT
  5019.     END_CASE
  5020.  
  5021.     CASE (TRANSFORM_TOKEN)
  5022.       Local_Trans = Parse_Transform ();
  5023.       if (Test_Redefine(Previous,TRANSFORM_ID_TOKEN))
  5024.         Destroy_Transform((TRANSFORM *)Constant_Ptr->Constant_Data);
  5025.       Constant_Ptr->Constant_Type = TRANSFORM_ID_TOKEN;
  5026.       Constant_Ptr->Constant_Data = (char *) Local_Trans;
  5027.       EXIT
  5028.     END_CASE
  5029.  
  5030.     CASE4 (STRING_LITERAL_TOKEN,CHR_TOKEN,SUBSTR_TOKEN,STR_TOKEN)
  5031.     CASE4 (CONCAT_TOKEN,STRUPR_TOKEN,STRLWR_TOKEN,STRING_ID_TOKEN)
  5032.       UNGET
  5033.       Temp_Data= Parse_String();
  5034.       if (Test_Redefine(Previous,STRING_ID_TOKEN))
  5035.         POV_FREE(Constant_Ptr->Constant_Data);
  5036.       Constant_Ptr->Constant_Type = STRING_ID_TOKEN;
  5037.       Constant_Ptr->Constant_Data = Temp_Data;
  5038.       EXIT
  5039.     END_CASE
  5040.  
  5041.     OTHERWISE
  5042.       UNGET
  5043.       Local_Object = Parse_Object ();
  5044.       if (Test_Redefine(Previous,OBJECT_ID_TOKEN))
  5045.         Destroy_Object((OBJECT *)Constant_Ptr->Constant_Data);
  5046.       Constant_Ptr->Constant_Type = OBJECT_ID_TOKEN;
  5047.       Constant_Ptr->Constant_Data = (char *) Local_Object;
  5048.       EXIT
  5049.     END_CASE
  5050.  
  5051.   END_EXPECT
  5052. }
  5053.  
  5054.  
  5055.  
  5056. /*****************************************************************************
  5057. *
  5058. * FUNCTION
  5059. *
  5060. * INPUT
  5061. *   
  5062. * OUTPUT
  5063. *   
  5064. * RETURNS
  5065. *   
  5066. * AUTHOR
  5067. *   
  5068. * DESCRIPTION
  5069. *
  5070. * CHANGES
  5071. *
  5072. ******************************************************************************/
  5073.  
  5074. static void Link (New_Object, Field, Old_Object_List)
  5075.   OBJECT *New_Object, **Field, **Old_Object_List;
  5076.   {
  5077.   *Field = *Old_Object_List;
  5078.   *Old_Object_List = New_Object;
  5079.   }
  5080.  
  5081.  
  5082.  
  5083. /*****************************************************************************
  5084. *
  5085. * FUNCTION
  5086. *
  5087. * INPUT
  5088. *
  5089. * OUTPUT
  5090. *   
  5091. * RETURNS
  5092. *   
  5093. * AUTHOR
  5094. *   
  5095. * DESCRIPTION
  5096. *
  5097. * CHANGES
  5098. *
  5099. ******************************************************************************/
  5100.  
  5101. void Link_Textures (Old_Textures, New_Textures)
  5102.   TEXTURE **Old_Textures;
  5103.   TEXTURE  *New_Textures;
  5104.   {
  5105.    TEXTURE *Layer;
  5106.    
  5107.    if (New_Textures == NULL)
  5108.      return;
  5109.  
  5110.    if ((*Old_Textures) != NULL)
  5111.    {
  5112.       if ((*Old_Textures)->Type != PLAIN_PATTERN) 
  5113.       {
  5114.          Error("Cannot layer over a patterned texture.\n");
  5115.       }
  5116.    }
  5117.    for (Layer = New_Textures ;
  5118.         Layer->Next != NULL ;
  5119.         Layer = (TEXTURE *)Layer->Next)
  5120.      {}
  5121.  
  5122.    Layer->Next = (TPATTERN *)*Old_Textures;
  5123.    *Old_Textures = New_Textures;
  5124.  
  5125.    if ((New_Textures->Type != PLAIN_PATTERN) && (New_Textures->Next != NULL))
  5126.    {
  5127.       Error("Cannot layer a patterned texture over another.\n");
  5128.    }
  5129.   }
  5130.  
  5131.  
  5132.  
  5133. /*****************************************************************************
  5134. *
  5135. * FUNCTION
  5136. *
  5137. * INPUT
  5138. *
  5139. * OUTPUT
  5140. *
  5141. * RETURNS
  5142. *
  5143. * AUTHOR
  5144. *
  5145. * DESCRIPTION
  5146. *
  5147. * CHANGES
  5148. *
  5149. ******************************************************************************/
  5150.  
  5151. static
  5152. char *Get_Token_String (Token_Id)
  5153.   TOKEN Token_Id;
  5154.   {
  5155.   register int i;
  5156.  
  5157.   for (i = 0 ; i < LAST_TOKEN ; i++)
  5158.      if (Reserved_Words[i].Token_Number == Token_Id)
  5159.         return (Reserved_Words[i].Token_Name);
  5160.   return ("");
  5161.   }
  5162.  
  5163.  
  5164.  
  5165. /*****************************************************************************
  5166. *
  5167. * FUNCTION
  5168. *
  5169. * INPUT
  5170. *
  5171. * OUTPUT
  5172. *
  5173. * RETURNS
  5174. *
  5175. * AUTHOR
  5176. *
  5177. * DESCRIPTION
  5178. *
  5179. * CHANGES
  5180. *
  5181. ******************************************************************************/
  5182.  
  5183. static int Test_Redefine(Previous,a)
  5184.   int Previous;
  5185.   int a;
  5186.   {
  5187.   char *old, *new;
  5188.  
  5189.   if (Previous == IDENTIFIER_TOKEN)
  5190.     return (FALSE);
  5191.   if (Previous != a)
  5192.     {old = Get_Token_String (Previous);
  5193.      new = Get_Token_String (a);
  5194.      Error ("Attempted to redefine %s as %s.", old, new);
  5195.     }
  5196.   return (TRUE);
  5197.   }
  5198.  
  5199.  
  5200.  
  5201. /*****************************************************************************
  5202. *
  5203. * FUNCTION
  5204. *
  5205. * INPUT
  5206. *
  5207. * OUTPUT
  5208. *
  5209. * RETURNS
  5210. *
  5211. * AUTHOR
  5212. *
  5213. * DESCRIPTION
  5214. *
  5215. * CHANGES
  5216. *
  5217. ******************************************************************************/
  5218.  
  5219. void Parse_Error (Token_Id)
  5220.   TOKEN Token_Id;
  5221.   {
  5222.   char *expected;
  5223.  
  5224.   expected = Get_Token_String (Token_Id);
  5225.   Parse_Error_Str(expected);
  5226.   }
  5227.  
  5228.  
  5229.  
  5230. /*****************************************************************************
  5231. *
  5232. * FUNCTION
  5233. *
  5234. * INPUT
  5235. *
  5236. * OUTPUT
  5237. *
  5238. * RETURNS
  5239. *
  5240. * AUTHOR
  5241. *
  5242. * DESCRIPTION
  5243. *
  5244. * CHANGES
  5245. *
  5246. ******************************************************************************/
  5247.  
  5248. void Parse_Error_Str (str)
  5249.   char *str;
  5250.   {
  5251.    Where_Error ();
  5252.    Error_Line("%s expected but", str);
  5253.    Found_Instead ();
  5254.   }
  5255.  
  5256.  
  5257.  
  5258. /*****************************************************************************
  5259. *
  5260. * FUNCTION
  5261. *
  5262. * INPUT
  5263. *
  5264. * OUTPUT
  5265. *
  5266. * RETURNS
  5267. *
  5268. * AUTHOR
  5269. *
  5270. * DESCRIPTION
  5271. *
  5272. * CHANGES
  5273. *
  5274. ******************************************************************************/
  5275.  
  5276. static void Found_Instead ()
  5277. {
  5278.   char *found;
  5279.   
  5280.   Stage=STAGE_FOUND_INSTEAD;
  5281.  
  5282.   switch(Token.Token_Id)
  5283.   {
  5284.     case IDENTIFIER_TOKEN:
  5285.       Error (" undeclared identifier '%s' found instead.\n", Token.Token_String);
  5286.       break;
  5287.       
  5288.     case VECTOR_FUNCT_TOKEN:
  5289.       found = Get_Token_String (Token.Function_Id);
  5290.       Error (" vector function '%s' found instead.\n", found);
  5291.       break;
  5292.       
  5293.     case FLOAT_FUNCT_TOKEN:
  5294.       found = Get_Token_String (Token.Function_Id);
  5295.       Error (" float function '%s' found instead.\n", found);
  5296.       break;
  5297.  
  5298.     case COLOUR_KEY_TOKEN:
  5299.       found = Get_Token_String (Token.Function_Id);
  5300.       Error (" color keyword '%s' found instead.\n", found);
  5301.       break;
  5302.  
  5303.     default:
  5304.       found = Get_Token_String (Token.Token_Id);
  5305.       Error (" %s found instead.\n", found);
  5306.   }
  5307. }
  5308.   
  5309.  
  5310.  
  5311. /*****************************************************************************
  5312. *
  5313. * FUNCTION
  5314. *
  5315. * INPUT
  5316. *
  5317. * OUTPUT
  5318. *
  5319. * RETURNS
  5320. *
  5321. * AUTHOR
  5322. *
  5323. * DESCRIPTION
  5324. *
  5325. * CHANGES
  5326. *
  5327. ******************************************************************************/
  5328.  
  5329. void Warn_State (Token_Id,Type)
  5330.   TOKEN Token_Id, Type;
  5331.   {
  5332.   char *found;
  5333.   char *should;
  5334.  
  5335.   found = Get_Token_String (Token_Id);
  5336.   should = Get_Token_String (Type);
  5337.   Warning (1.5, "%s:%d: warning: Found %s that should be in %s statement.\n",
  5338.            Token.Filename, Token.Token_Line_No+1, found, should);
  5339.   }
  5340.  
  5341.  
  5342.  
  5343. /*****************************************************************************
  5344. *
  5345. * FUNCTION
  5346. *
  5347. * INPUT
  5348. *
  5349. * OUTPUT
  5350. *
  5351. * RETURNS
  5352. *
  5353. * AUTHOR
  5354. *
  5355. * DESCRIPTION
  5356. *
  5357. * CHANGES
  5358. *
  5359. ******************************************************************************/
  5360.  
  5361. void Warn (Level, str)
  5362.   DBL Level;
  5363.   char *str;
  5364.   {
  5365.   if (opts.Language_Version < Level)
  5366.     return;
  5367.  
  5368.   Warning(Level, "%s:%d: warning: %s\n", Token.Filename, Token.Token_Line_No+1, str);
  5369.   }
  5370.  
  5371.  
  5372.  
  5373. /*****************************************************************************
  5374. *
  5375. * FUNCTION
  5376. *
  5377. * INPUT
  5378. *
  5379. * OUTPUT
  5380. *
  5381. * RETURNS
  5382. *
  5383. * AUTHOR
  5384. *
  5385. * DESCRIPTION
  5386. *
  5387. * CHANGES
  5388. *
  5389. ******************************************************************************/
  5390.  
  5391. void MAError (str,size)
  5392.   char *str;
  5393.   long size;
  5394.   {
  5395.   Error ("Out of memory.  Cannot allocate %ld bytes for %s.\n",size,str);
  5396.   }
  5397.  
  5398.  
  5399.  
  5400. /*****************************************************************************
  5401. *
  5402. * FUNCTION
  5403. *
  5404. * INPUT
  5405. *
  5406. * OUTPUT
  5407. *
  5408. * RETURNS
  5409. *
  5410. * AUTHOR
  5411. *
  5412. * DESCRIPTION
  5413. *
  5414. * CHANGES
  5415. *
  5416. ******************************************************************************/
  5417.  
  5418. /* Write a token out to the token file */
  5419.  
  5420. void Write_Token (Token_Id, Data_File)
  5421.   TOKEN Token_Id;
  5422.   DATA_FILE *Data_File;
  5423.  
  5424.   {
  5425.    Token.Token_Line_No = Data_File->Line_Number;
  5426.    Token.Filename = Data_File->Filename;
  5427.    Token.Token_String = String;
  5428.    Token.Constant_Data = NULL;
  5429.    Token.Token_Id = Token_Id;
  5430.  
  5431.    Token.Constant_Index = (int) Token.Token_Id - (int) LAST_TOKEN;
  5432.  
  5433.    if (Token.Constant_Index >= 0)
  5434.    {
  5435.       if (Token.Constant_Index <= Number_Of_Constants)
  5436.       {
  5437.         Token.Constant_Data = Constants[Token.Constant_Index].Constant_Data;
  5438.         Token.Token_Id=Constants[Token.Constant_Index].Constant_Type;
  5439.       }
  5440.       else 
  5441.       {
  5442.          Token.Token_Id = IDENTIFIER_TOKEN;
  5443.       }
  5444.    }
  5445.  
  5446.    Token.Function_Id = Token.Token_Id;
  5447.    if (Token.Token_Id < FLOAT_FUNCT_TOKEN)
  5448.      Token.Token_Id = FLOAT_FUNCT_TOKEN;
  5449.    else
  5450.      if (Token.Token_Id < VECTOR_FUNCT_TOKEN)
  5451.        Token.Token_Id = VECTOR_FUNCT_TOKEN;
  5452.      else
  5453.        if (Token.Token_Id < COLOUR_KEY_TOKEN)
  5454.          Token.Token_Id = COLOUR_KEY_TOKEN;
  5455.   }
  5456.  
  5457.  
  5458.  
  5459. /*****************************************************************************
  5460. *
  5461. * FUNCTION
  5462. *
  5463. * INPUT
  5464. *
  5465. * OUTPUT
  5466. *
  5467. * RETURNS
  5468. *
  5469. * AUTHOR
  5470. *
  5471. * DESCRIPTION
  5472. *
  5473. * CHANGES
  5474. *
  5475. ******************************************************************************/
  5476.  
  5477. static void Post_Process (Object,Parent)
  5478. OBJECT *Object, *Parent;
  5479. {
  5480.   DBL Volume;
  5481.   OBJECT *Sib;
  5482.  
  5483.   if (Object == NULL)
  5484.     return;
  5485.  
  5486.   if (Parent != NULL)
  5487.   {
  5488.     if (Object->Texture == NULL)
  5489.       Object->Texture = Copy_Texture_Pointer (Parent->Texture);
  5490.  
  5491. /*
  5492.     else
  5493.       if (Parent->Texture != NULL)
  5494.       {
  5495.         Local_Texture = Copy_Textures (Parent->Texture);
  5496.         Link_Textures (&(Object->Texture), Local_Texture);
  5497.       }
  5498. */ /* Removed for backward compat with 1.0.  May put back in. CEY 12/92 */
  5499.  
  5500.     if (Test_Flag(Parent, NO_SHADOW_FLAG))
  5501.       Set_Flag(Object, NO_SHADOW_FLAG);
  5502.   }
  5503.  
  5504.   if ((Object->Texture == NULL) &&
  5505.       !(Object->Type & TEXTURED_OBJECT) &&
  5506.       !(Object->Type & LIGHT_SOURCE_OBJECT))
  5507.     Object->Texture = Copy_Textures(Default_Texture);
  5508.  
  5509.   if (Object->Type & COMPOUND_OBJECT)
  5510.   {
  5511.     if (Object->Type & LIGHT_SOURCE_OBJECT)
  5512.     {
  5513.        ((LIGHT_SOURCE *)Object)->Next_Light_Source = Frame.Light_Sources;
  5514.        Frame.Light_Sources = (LIGHT_SOURCE *)Object;
  5515.        Frame.Number_Of_Light_Sources++;
  5516.     }
  5517.  
  5518.     for (Sib = ((CSG *)Object)->Children; Sib != NULL; Sib = Sib->Sibling)
  5519.       Post_Process(Sib, Object);
  5520.   }
  5521.   else
  5522.   {
  5523.     if (Object->Texture == NULL)
  5524.       Object->Texture = Copy_Textures(Default_Texture);
  5525.  
  5526.     if (Object->Texture->Type == PLAIN_PATTERN)
  5527.       if (Object->Texture->Tnormal != NULL)
  5528.         Object->Type |= DOUBLE_ILLUMINATE;
  5529.   }
  5530.  
  5531.   Post_Textures (Object->Texture);
  5532.  
  5533.   /* Test wether the object is finite or infinite. [DB 9/94] */
  5534.  
  5535.   BOUNDS_VOLUME(Volume, Object->BBox);
  5536.  
  5537.   if (Volume > INFINITE_VOLUME)
  5538.   {
  5539.     Set_Flag(Object, INFINITE_FLAG);
  5540.   }
  5541.  
  5542.   /* Test wether the object is opaque or not. [DB 8/94] */
  5543.  
  5544.   /*
  5545.    * Blobs and meshes have to be handled speratly because
  5546.    * of the multiple textures.
  5547.    */
  5548.  
  5549.   if ((Object->Methods != &Blob_Methods) &&
  5550.       (Object->Methods != &Mesh_Methods) &&
  5551.       (Test_Opacity(Object->Texture)))
  5552.   {
  5553.     Set_Flag(Object, OPAQUE_FLAG);
  5554.   }
  5555.  
  5556.   if (Object->Methods == &Blob_Methods)
  5557.   {
  5558.     Test_Blob_Opacity((BLOB *)Object);
  5559.   }
  5560.  
  5561.   if (Object->Methods == &Mesh_Methods)
  5562.   {
  5563.     Test_Mesh_Opacity((MESH *)Object);
  5564.   }
  5565. }
  5566.  
  5567.  
  5568.  
  5569. /*****************************************************************************
  5570. *
  5571. * FUNCTION
  5572. *
  5573. * INPUT
  5574. *
  5575. * OUTPUT
  5576. *
  5577. * RETURNS
  5578. *
  5579. * AUTHOR
  5580. *
  5581. * DESCRIPTION
  5582. *
  5583. * CHANGES
  5584. *
  5585. ******************************************************************************/
  5586.  
  5587. static void Destroy_Constants ()
  5588.   {
  5589.    int i;
  5590.    char *Ptr;
  5591.  
  5592.    for (i=1; i <= Number_Of_Constants; i++)
  5593.      {
  5594.       Ptr = Constants[i].Constant_Data;
  5595.       switch (Constants[i].Constant_Type)
  5596.         {
  5597.          case COLOUR_ID_TOKEN:
  5598.            Destroy_Colour((COLOUR *)Ptr);
  5599.            break;
  5600.          case VECTOR_ID_TOKEN:
  5601.            Destroy_Vector((VECTOR *)Ptr);
  5602.            break;
  5603.          case FLOAT_ID_TOKEN:
  5604.            Destroy_Float((DBL *)Ptr);
  5605.            break;
  5606.          case PIGMENT_ID_TOKEN:
  5607.            Destroy_Pigment((PIGMENT *)Ptr);
  5608.            break;
  5609.          case TNORMAL_ID_TOKEN:
  5610.            Destroy_Tnormal((TNORMAL *)Ptr);
  5611.            break;
  5612.          case FINISH_ID_TOKEN:
  5613.            Destroy_Finish((FINISH *)Ptr);
  5614.            break;
  5615.          case HALO_ID_TOKEN:
  5616.            Destroy_Halo((HALO *)Ptr);
  5617.            break;
  5618.          case TEXTURE_ID_TOKEN:
  5619.            Destroy_Textures((TEXTURE *)Ptr);
  5620.            break;
  5621.          case OBJECT_ID_TOKEN:
  5622.            Destroy_Object((OBJECT *)Ptr);
  5623.            break;
  5624.          case COLOUR_MAP_ID_TOKEN:
  5625.          case PIGMENT_MAP_ID_TOKEN:
  5626.          case SLOPE_MAP_ID_TOKEN:
  5627.          case TEXTURE_MAP_ID_TOKEN:
  5628.          case NORMAL_MAP_ID_TOKEN:
  5629.            Destroy_Blend_Map((BLEND_MAP *)Ptr);
  5630.            break;
  5631.          case TRANSFORM_ID_TOKEN:
  5632.            Destroy_Transform((TRANSFORM *)Ptr);
  5633.            break;
  5634.          case CAMERA_ID_TOKEN:
  5635.            Destroy_Camera((CAMERA *)Ptr);
  5636.            break;
  5637.          case RAINBOW_ID_TOKEN:
  5638.            Destroy_Rainbow((RAINBOW *)Ptr);
  5639.            break;
  5640.          case FOG_ID_TOKEN:
  5641.            Destroy_Fog((FOG *)Ptr);
  5642.            break;
  5643.          case SKYSPHERE_ID_TOKEN:
  5644.            Destroy_Skysphere((SKYSPHERE *)Ptr);
  5645.            break;
  5646.          case ATMOSPHERE_ID_TOKEN:
  5647.            Destroy_Atmosphere((ATMOSPHERE *)Ptr);
  5648.            break;
  5649.          case STRING_ID_TOKEN:
  5650.            POV_FREE(Ptr);
  5651.            break;
  5652.         }
  5653.      }
  5654.  
  5655.      POV_FREE(Constants);
  5656.   }
  5657.  
  5658. /*****************************************************************************
  5659. *
  5660. * FUNCTION
  5661. *
  5662. *   Link_To_Frame
  5663. *
  5664. * INPUT
  5665. *
  5666. *   Object - Pointer to object
  5667. *   
  5668. * OUTPUT
  5669. *
  5670. *   Object
  5671. *   
  5672. * RETURNS
  5673. *   
  5674. * AUTHOR
  5675. *
  5676. *   POV-Ray Team
  5677. *   
  5678. * DESCRIPTION
  5679. *
  5680. *   -
  5681. *
  5682. * CHANGES
  5683. *
  5684. *   Sep 1994 : Added optional splitting of bounded unions if children are
  5685. *              finite. Added removing of unnecessary bounding. [DB]
  5686. *
  5687. ******************************************************************************/
  5688.  
  5689. static void Link_To_Frame(Object)
  5690. OBJECT *Object;
  5691. {
  5692.   int finite;
  5693.   DBL Volume;
  5694.   OBJECT *This_Sib, *Next_Sib;
  5695.  
  5696.   if (Object == NULL)           /* patches a memory addressing error jdm mar/95 */
  5697.     return;
  5698.  
  5699.   /* Remove bounding object if object is cheap to intersect. [DB 8/94]  */
  5700.  
  5701.   if ((opts.Options & REMOVE_BOUNDS) && (Object->Bound != NULL))
  5702.   {
  5703.     if ((Object->Methods != &CSG_Union_Methods)        &&
  5704.         (Object->Methods != &CSG_Intersection_Methods) &&
  5705.         (Object->Methods != &CSG_Merge_Methods)        &&
  5706.         (Object->Methods != &Poly_Methods)             &&
  5707.         (Object->Methods != &TTF_Methods))
  5708.     {
  5709.       /* Destroy only, if bounding object is not used as clipping object. */
  5710.  
  5711.       if (Object->Bound != Object->Clip)
  5712.       {
  5713.         Destroy_Object(Object->Bound);
  5714.       }
  5715.  
  5716.       Object->Bound = NULL;
  5717.  
  5718.       Warn(0.0, "Unnecessary bounding object removed.");
  5719.     }
  5720.   }
  5721.  
  5722.   /*
  5723.    * Link the object to the frame if it's not a CSG union object,
  5724.    * if it's clipped or if bounding slabs aren't used.
  5725.    */
  5726.  
  5727.   if ((Object->Methods != &CSG_Union_Methods) ||
  5728.       (Object->Clip != NULL) ||
  5729.       (!opts.Use_Slabs))
  5730.   {
  5731.     Link(Object, &(Object->Sibling), &(Frame.Objects));
  5732.  
  5733.     return;
  5734.   }
  5735.  
  5736.   /*
  5737.    * [DB 8/94]
  5738.    *
  5739.    * The object is a CSG union object. It will be split if all siblings are
  5740.    * finite, i.e. the volume of the bounding box doesn't exceed a threshold.
  5741.    */
  5742.  
  5743.   if (Object->Bound != NULL)
  5744.   {
  5745.     /* Test if all siblings are finite. */
  5746.  
  5747.     finite = TRUE;
  5748.  
  5749.     for (This_Sib = ((CSG *)Object)->Children; This_Sib != NULL; This_Sib = This_Sib->Sibling)
  5750.     {
  5751.       BOUNDS_VOLUME(Volume, This_Sib->BBox);
  5752.  
  5753.       if (Volume > BOUND_HUGE)
  5754.       {
  5755.         finite = FALSE;
  5756.  
  5757.         break;
  5758.       }
  5759.     }
  5760.  
  5761.     /*
  5762.      * If the union has infinite children or splitting is not used link
  5763.      * the union to the frame.
  5764.      */
  5765.  
  5766.     if ((!finite) || !(opts.Options & SPLIT_UNION))
  5767.     {
  5768.       if (finite)
  5769.       {
  5770.         Warn(0.0, "CSG union unnecessarily bounded.");
  5771.       }
  5772.  
  5773.       Link(Object, &(Object->Sibling), &(Frame.Objects));
  5774.  
  5775.       return;
  5776.     }
  5777.  
  5778.     Warn(0.0, "Bounded CSG union split.");
  5779.   }
  5780.  
  5781.   /* Link all siblings of a union to the frame. */
  5782.  
  5783.   for (This_Sib = ((CSG *)Object)->Children; This_Sib != NULL; This_Sib = Next_Sib)
  5784.   {
  5785.     /* Link_To_Frame() changes Sibling so save it */
  5786.  
  5787.     Next_Sib = This_Sib->Sibling;
  5788.  
  5789.     /* Sibling is no longer inside a CSG object. */
  5790.  
  5791.     This_Sib->Type &= ~IS_CHILD_OBJECT;
  5792.  
  5793.     Link_To_Frame (This_Sib);
  5794.   }
  5795.  
  5796. /*
  5797.   Object->Texture = NULL;
  5798. */
  5799.  
  5800.   Object->Sibling = NULL;
  5801.  
  5802.   ((CSG *)Object)->Children = NULL;
  5803.  
  5804.   Destroy_Object (Object);
  5805. }
  5806.  
  5807.  
  5808.  
  5809. /*****************************************************************************
  5810. *
  5811. * FUNCTION
  5812. *
  5813. * INPUT
  5814. *
  5815. * OUTPUT
  5816. *
  5817. * RETURNS
  5818. *
  5819. * AUTHOR
  5820. *
  5821. * DESCRIPTION
  5822. *
  5823. * CHANGES
  5824. *
  5825. ******************************************************************************/
  5826.  
  5827. void Only_In(s1,s2)
  5828. char *s1, *s2;
  5829. {
  5830.   Error("Keyword '%s' can only be used in a %s statement.",s1,s2);
  5831. }
  5832.  
  5833.  
  5834.  
  5835. /*****************************************************************************
  5836. *
  5837. * FUNCTION
  5838. *
  5839. * INPUT
  5840. *
  5841. * OUTPUT
  5842. *
  5843. * RETURNS
  5844. *
  5845. * AUTHOR
  5846. *
  5847. * DESCRIPTION
  5848. *
  5849. * CHANGES
  5850. *
  5851. ******************************************************************************/
  5852.  
  5853. void Not_With(s1,s2)
  5854. char *s1, *s2;
  5855. {
  5856.   Error("Keyword '%s' cannot be used %s.",s1,s2);
  5857. }
  5858.  
  5859.